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();
}
}
程序执行结果: