线程通信的三方方式(线程唤醒)

文章中的Console.log()使用的是 hutool工具

  • 方式1和方式2,必须搭配锁🔒使用,而方式3可以不使用锁

1、使用wait notify synchronized 实现线程唤醒机制

实现线程唤醒机制,但不保证是精确唤醒

private static void imp1() {
    final Object lock = new Object();
    new Thread(() -> {
        synchronized (lock) {
            Console.log("{} 开始等待...", Thread.currentThread().getName());
            try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}
            Console.log("{} 被唤醒", Thread.currentThread().getName());
        }
    }, "线程1").start();

    new Thread(() -> {
        synchronized (lock) {
            try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}
            Console.log("{} 执行唤醒操作", Thread.currentThread().getName());
            lock.notify();
        }
    }, "线程2").start();
}

2、使用 ReentrantLock,Conditionawaitsignal方法

可以实现精确唤醒

private static void imp2() {
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    new Thread(() -> {
        lock.lock();
        try {
            Console.log("{} 开始等待...", Thread.currentThread().getName());
            condition.await();
            Console.log("{} 被唤醒", Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }, "线程1").start();

    new Thread(() -> {
        lock.lock();
        try {
            TimeUnit.SECONDS.sleep(1);
            Console.log("{} 执行唤醒操作", Thread.currentThread().getName());
            condition.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }, "线程2").start();
}

3、使用 LockSupportpark(),unpark(线程1)方法

可以实现精确唤醒

注意下面休眠位置unpark 可以在 park 之前执行,这样 t1线程在执行到park处的时候,不会阻塞

    private static void imp3() {
        Thread t1 = new Thread(() -> {
            try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
            Console.log("{} 开始等待...LockSupport", Thread.currentThread().getName());
            LockSupport.park();
            Console.log("{} 被唤醒", Thread.currentThread().getName());
        }, "线程1");

        t1.start();

        Thread t2 = new Thread(() -> {
            Console.log("{} 执行唤醒操作", Thread.currentThread().getName());
            LockSupport.unpark(t1);
        }, "线程2");
        t2.start();
    }
posted @ 2022-01-08 23:37  周星星、同学  阅读(343)  评论(0编辑  收藏  举报