java线程状态变迁图

从图中可以看出Java 线程等待方法是将线程从Runnable状态转换为Waiting状态,Java线程的唤醒方法是将线程从Waiting状态唤醒进入Runnable状态
在Java中线程的等待和唤醒主要是分为3组:

  • Object.wait() 和 Object.notify()
  • LockSupport.park() 和 LockSupport.unpark(Thread thread)
  • Condition.await() 和 Condition.signal() ---- 这组内部靠LockSupport.park() 和 LockSupport.unpark(Thread thread) 进行线程等待和唤醒

Object.wait() 和 Object.notify()

wait() 和 notify() 相关方法


表中的方法必须要在获得监视器monitor的情况下使用

简单使用wait()和notify()方法示例:

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");
        threadA.start();
        Thread.sleep(1000);
        synchronized (object){
            System.out.println("main 已获得监视器");
            object.notify();
        }
    }
}

notify()和notifyAll()的区别演示:使用notify() 只能唤醒一个在对象上等待的线程,使用notifyAll()可以唤醒所有在对象上等待的线程。

使用notify()

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadB 已进入获得监视器");
                    object.wait();
                    System.out.println("threadB 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadB");
        threadA.start();
        threadB.start();
        Thread.sleep(1000);
        synchronized (object){
            System.out.println("main 已获得监视器");
            object.notify();
            System.out.println("main 已唤醒一个线程");
        }
    }
}


结果线程B未能被唤醒。

改用notifyAll()

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadB 已进入获得监视器");
                    object.wait();
                    System.out.println("threadB 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadB");
        threadA.start();
        threadB.start();
        Thread.sleep(1000);
        synchronized (object){
            System.out.println("main 已获得监视器");
            object.notifyAll();
            System.out.println("main 已唤醒一个线程");
        }
    }
}


线程A,B都被唤醒了,程序正常结束。

wait(long) 方法的使用: 等待时间过了没被唤醒自己进入Runnable状态

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait(1000 * 60);
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");
        threadA.start();
    }
}

程序执行结果

调用wait(long) 方法进入timed_waiting状态

等待时间过了进入runnable状态

注意线程中断也会唤醒wait()中的线程

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("threadA 已被唤醒");
            }
        }, "threadA");
        threadA.start();
        Thread.sleep(1000);
        threadA.interrupt();
    }
}

程序执行结果

LockSupport.park() 和 LockSupport.unpark(Thread thread)

LockSupport.park() 和 LockSupport.unpark(Thread thread) 并不依赖同步方法

LockSupport.park() 和 LockSupport.unpark(Thread thread) 相关方法

简单使用

public class ParkTest {

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            System.out.println("ThreadA 开始运行了");
            LockSupport.park();
            System.out.println("ThreadA 继续运行了");
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        LockSupport.unpark(threadA);
    }
}

注意线程中断也会唤醒LockSupport.park()中的线程

public class ParkTest {

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            System.out.println("ThreadA 开始运行了");
            LockSupport.park();
            System.out.println("ThreadA 继续运行了");
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        threadA.interrupt();
    }
}

Condition.await() 和 Condition.signal()

Condition.await() 和 Condition.signal() 相关方法

简单使用

public class ConditionTest {

    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程A 获得了lock锁");
                condition.await();
            } catch (InterruptedException e) {
                System.out.println("线程A 被唤醒了");
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        lock.lock();
        try {
            System.out.println("main 线程获得了lock锁");
            condition.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
          lock.unlock();
        }
    }
}

程序执行结果:

注意线程中断也会唤醒condition.await()中的线程

public class ConditionTest {

    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程A 获得了lock锁");
                condition.await();
            } catch (InterruptedException e) {
                System.out.println("线程A 被唤醒了");
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        threadA.interrupt();
        condition.signal();
    }
}

程序执行结果:

Condition.signalAll() 用法上和Object.notifyAll() 类似

参考:《Java并发编程的艺术》
posted on 2023-07-09 22:57  旅途的痕迹  阅读(247)  评论(0编辑  收藏  举报