美文网首页
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