类A里面定义有一个线程对象,通过内部线程类实现。
类B里面有类A的实例对像,同时还有一些其他的功能。
在类C里面实例化类B,类C里有两个方法操作同一个类A里面的线程对象,一个方法要达到暂停(不是停止退出)类A里面的线程对象,宁一个方法要恢复类A里面的线程对象,那么在类C里该如何实现这两个方法?
调用类a里面线程对象的wait方法总是报错,报没有得到什么锁的错误
wait方法会释放掉锁,但前提是要有锁可以释放才行呀,所以你在调用wait方法的时候需要加上一个synchronized,我写了下代码,你看看对不对。
类A
public class A {
private boolean isPaused = false;
private Thread thread;
public A() {
thread = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// do something
synchronized (A.this) {
while (isPaused) {
try {
A.this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
});
}
public void start() {
thread.start();
}
public void pause() {
isPaused = true;
}
public void resume() {
synchronized (this) {
isPaused = false;
this.notify();
}
}
}
类B
public class B {
private A a;
public B() {
a = new A();
}
public void startThread() {
a.start();
}
public void pauseThread() {
a.pause();
}
public void resumeThread() {
a.resume();
}
}
类C
public class C {
public static void main(String[] args) {
B b = new B();
b.startThread();
// pause thread after 5 seconds
new Timer().schedule(new TimerTask() {
@Override
public void run() {
b.pauseThread();
}
}, 5000);
// resume thread after 10 seconds
new Timer().schedule(new TimerTask() {
@Override
public void run() {
b.resumeThread();
}
}, 10000);
}
}
volatile只是保证了可见性,可以让其他线程看到某一线程修改后的数据。
例如考试,A和B抄小马的答案,此时的小马就代表主内存,但是离交卷还有几秒,B反复思考一道题最终更改为了正确答案并告诉小马,你这个错了,快改过来,此时小马听后立马改掉了答案,A看到了小马更改了答案,因为A和B坐在不同的方向,就像线程一样不能交互,只能通过主内存的共享数据进行交互,B告诉小马时A并不知道,直到小马更改完答案后A才知道,但此时卷子已经提交,A没有时间修改。在线程中就导致了覆盖的现象。A,B加完1给主线程,B给主线程回写完了,但是此刻A也同时写回了,主内存值本应为2,但是被覆盖为1。
解决方法:
1.加synchronized同步锁。(但是此处使用synchronized显得太重了,杀鸡用牛刀!)
2.使用juc下的AtomicInteger可以保证原子性(CAS自旋锁),代码如下:
package volatiledemo;
import java.util.concurrent.atomic.AtomicInteger;
public class Mydata {
volatile int grade = 0 ;
public void mydata(){
this.grade = 60;
}
public void addadd(){
grade++;
}
//new AtomicInteger(); ()里不写默认为0,相当于现在atomicInteger = 0
AtomicInteger atomicInteger = new AtomicInteger();
public void addMyAtomic(){
//等同于++ 带原子性的++
atomicInteger.getAndIncrement();
}
}
package volatiledemo;
public class VolatileDemo {
public static void main(String[] args) {
Mydata mydata = new Mydata();
//循环创建20个线程,每个线程执行addadd方法一千次
for (int i = 1; i <=20 ; i++) {
new Thread(() ->{
for (int j = 1; j <=1000 ; j++) {
mydata.addadd();
mydata.addMyAtomic();
}
},String.valueOf(i)).start();
}
/**Thread.activeCount()
* 此方法返回活动线程的当前线程的线程组中的数量。
*/
//如果当前线程大于2,代表除了当前main线程还有其他后台GC线程
while (Thread.activeCount()>2){
/**
* Thread.yield()
* 使当前线程从执行状态(运行状态)变为可执行态(就绪状态)
*/
//当还有其他线程时,main线程进行礼让,让其他线程先执行
Thread.yield();
}
//输出20个线程执行完毕后grade的最终值
System.out.println(Thread.currentThread().getName()+"grade final value:"+mydata.grade);
System.out.println(Thread.currentThread().getName()+"atomicInteger final value:"+mydata.atomicInteger);
}
}
结果如下: