Java使用wait/notify实现线程间通信下篇

2022-12-14,,

wait()和notify()是直接隶属于Object类,也就是说所有对象都拥有这一对方法,下面这篇文章主要给大家介绍了关于使用wait/notify实现线程间通信的相关资料,需要的朋友可以参考下

目录
  • 1. 当 interrupt() 方法遇到 wait() 方法
  • 2. notify() 只通知一个线程
  • 3. notifyAll() 唤醒所有线程
  • 4. 方法 wait(long)的使用

上一节针对wait/notify实现线程间通信的基本概念做了讲解(Java使用wait/notify实现线程间通信上篇),本节继续针对wait/notify实现线程间通信的其他知识点及特性进行讲解。

1. 当 interrupt() 方法遇到 wait() 方法

当线程调用锁对象的wait() 方法使线程呈等待状态时,调用线程对象的 interrupt() 方法会出现 InterruptedException 异常。

public class ThreadC7 {
    @Test
    public void test1() {
        try {
            Object obj = new Object();
            ThreadC7A threadC7A = new ThreadC7A(obj);
            threadC7A.start();
            Thread.sleep(2000);
            threadC7A.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class ServiceC7 {
    public void testMethod(Object obj) {
        try {
            synchronized (obj) {
                System.out.println("begin wait");
                obj.wait();
                System.out.println("begin end");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("出现异常了,wait状态的线程被interrupt了!");
        }
    }
}
class ThreadC7A extends Thread {
    private Object obj;
    public ThreadC7A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC7 serviceC7 = new ServiceC7();
        serviceC7.testMethod(obj);
    }
}

执行结果:

2. notify() 只通知一个线程

调用方法notify()一次只随机通知一个线程进行唤醒。

public class ThreadC8 {
    @Test
    public void test() {
        Object obj = new Object();
        ThreadC8A threadC8A = new ThreadC8A(obj);
        threadC8A.setName("threadC8A");
        threadC8A.start();
        ThreadC8B threadC8B = new ThreadC8B(obj);
        threadC8B.setName("threadC8B");
        threadC8B.start();
        ThreadC8C threadC8C = new ThreadC8C(obj);
        threadC8C.setName("threadC8C");
        threadC8C.start();
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            obj.notify();
        }
        while (Thread.activeCount() > 1) {
        }
    }
}
class ServiceC8 {
    public void service(Object obj) {
        try {
            synchronized (obj) {
                String threadName = Thread.currentThread().getName();
                System.out.println("begin wait,Thread Name:[" + threadName + "]");
                obj.wait();
                System.out.println("end wait,Thread Name:[" + threadName + "]");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class ThreadC8A extends Thread {
    private Object obj;
    public ThreadC8A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}
class ThreadC8B extends Thread {
    private Object obj;
    public ThreadC8B(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}
class ThreadC8C extends Thread {
    private Object obj;
    public ThreadC8C(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}

执行结果:

程序运行的效果如图所示,可以看出方法notify()仅随机唤醒一个线程。

当多次调用notify()方法时,会随机将等待wait状态的线程进行唤醒。更改代码如下:

再次运行,程序运行效果如图所示,可以看出所有的线程全部被唤醒。

多次调用notify()方法可唤醒全部WAITING中的线程。

3. notifyAll() 唤醒所有线程

前面的示例中通过多次调用 notify() 方法来实现唤醒3个线程,但并不能保证系统中仅有3个线程,也就是若notify()方法的调用次数小于线程对象的数量,会出现有部分线程对象无法被唤醒的情况。为了唤醒全部线程,可以使用notifyAll()方法。

更改代码如下:

再次运行,程序运行效果如图所示,可以看出所有的线程全部被唤醒。

4. 方法 wait(long)的使用

带一个参数的wait(long) 方法的功能是等待某一时间内是否有现成对锁进行唤醒,如果超过这个时间则自动唤醒。

public class ThreadC9 {
    @Test
    public void test() {
        Object obj = new Object();
        ThreadC9A threadC9A = new ThreadC9A(obj);
        threadC9A.start();
        while (Thread.activeCount() > 1) {
        }
    }
}
class ThreadC9A extends Thread {
    private Object obj;
    public ThreadC9A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        try {
            synchronized (obj) {
                long startTime = System.currentTimeMillis();
                System.out.println("begin wait,time:[" + startTime + "]");
                obj.wait(5000);
                long endTime = System.currentTimeMillis();
                System.out.println("end wait,time:[" + endTime + "] takes " + (endTime - startTime) + " ms");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果:

通过执行结果可以看出,在经过5000ms后,线程被唤醒。

到此这篇关于Java使用wait/notify实现线程间通信下篇的文章就介绍到这了,更多相关Java wait notify内容请搜索北冥有鱼以前的文章或继续浏览下面的相关文章希望大家以后多多支持北冥有鱼!

《Java使用wait/notify实现线程间通信下篇.doc》

下载本文的Word格式文档,以方便收藏与打印。