java主线程如何暂停子线程?

类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);
    }
}
  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/1093887
  • 除此之外, 这篇博客: Java volatile关键字中的 原子性即为保证完整性,不可分割,即某个线程在做操作时,是不能被加塞或者分割的,需要整体完整,要么同时成功,要么同时失败。而现在出现的情况,是因为线程之间出现了覆盖,A线程和B、C线程同时拿到数据进行加加操作,当A写回主内存时B或C并没来得及拿到更改后的共享数据,可能会出现被覆盖的效果,所以说volatile并不保证原子性。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 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);
        }
    }
    
    

    结果如下: