美文网首页
wait和notify的线程通信机制

wait和notify的线程通信机制

作者: 文景大大 | 来源:发表于2020-04-28 20:46 被阅读0次

    一、入门实例

    通过wait和notify/notiftAll可以实现多线程之间的通信。

    @Slf4j
    public class Thread1 implements Runnable {
        private String lock;
    
        public Thread1(String lock) {
            this.lock = lock;
        }
    
        @Override
        public void run() {
            synchronized (lock) {
                log.info("开始wait:{}", System.currentTimeMillis());
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("结束wait:{}", System.currentTimeMillis());
            }
        }
    }
    
    @Slf4j
    public class Thread2 implements Runnable {
        private String lock;
    
        public Thread2(String lock) {
            this.lock = lock;
        }
    
        @Override
        public void run() {
            synchronized (lock) {
                log.info("开始notify:{}", System.currentTimeMillis());
                lock.notify();
                log.info("结束notify:{}", System.currentTimeMillis());
            }
        }
    }
    
    @Slf4j
    public class Test001 {
        public static void main(String[] args) throws InterruptedException {
            String lock = "lock";
            Thread thread1 = new Thread(new Thread1(lock));
            Thread thread2 = new Thread(new Thread2(lock));
            thread1.start();
            Thread.sleep(3000);
            thread2.start();
        }
    }
    

    当thread1启动后,执行wait后,就会释放lock锁,从running状态变为blocked状态;

    当thread2启动后,能正常获取到lock锁,因此开始执行,执行notify随机唤醒一个等待lock锁的blocked状态的线程,但是thread2并没有执行完同步代码块,因此还不会释放锁,thread1因此还是处于blocked状态,只有等thread2执行完同步代码块,并释放锁之后,thread1才会回到runnable状态,等待CPU资源再进入running状态。

    因此,上述例子的打印结果为:

    开始wait:1587888213497
    开始notify:1587888216508
    结束notify:1587888216508
    结束wait:1587888216508
    

    二、使用要点

    • wait和notify必须在获取锁的状态下使用,比如上面例子中,我们都是在synchronized同步代码块中使用的;
    • wait会释放锁,使线程变为blocked状态,而sleep是不会释放锁的;
    • wait(long)标识在long时间后,自己唤醒自己,但是如果获取不到锁资源,仍然不能运行;
    • notify可以随机唤醒一个等待相同锁资源的线程,但是不会立即释放锁,需要等到同步代码块全部执行完成;
    • notifyAll是唤醒所有等待相同锁资源的线程,其余同notify;
    • notify必须确保在wait之后,否则通知过早,导致wait的线程无法被唤醒;

    三、线程状态说明

    • Runnable
      • 调用start开启一个线程;
      • 调用yield让出CPU资源;
      • 当前CPU时间片用完后,被其它高优先级的线程抢占了CPU资源;
      • Sleep结束后;
      • 阻塞方法执行完毕;
      • 获得了锁资源;
      • 等到了其它线程发出的唤醒通知;
      • resume方法恢复运行;
    • Running
      • 在Runnable状态下获取CPU时间片资源时;
    • Blocked
      • 调用sleep;
      • 调用了阻塞方法;
      • 需要的锁资源正在被其它线程使用中;
      • 等待其它线程的唤醒通知;
      • 调用suspend;
    • Destroy
      • 线程执行完毕后;

    相关文章

      网友评论

          本文标题:wait和notify的线程通信机制

          本文链接:https://www.haomeiwen.com/subject/xxvjwhtx.html