一、重要方法概览
类 | 方法名 | 说明 |
---|---|---|
Thread | sleep() | 让线程等待 |
join() | 等待其他线程执行完毕 | |
yield() | 放弃已经获取到的CPU资源 | |
currentThread() | 获取当前执行线程的引用 | |
start()、run() | 启动线程 | |
interrtupt() | 中断线程 | |
stop()、suspend()、resuem() | 已废弃 | |
Object | wait()、notify()、notifyAll() | 让线程暂时休息和唤醒 |
二、Object类中的wait()、notify()、notifyAll()
1.作用
- 阻塞阶段
执行wait()后,线程进入阻塞状态,wait()需要在synchronized的方法中使用。 - 唤醒阶段
notify()会唤醒某个正在等待锁的线程,如果有多个线程都在等待锁,则会选取其中任意一个唤醒。需要在synchronized的方法中使用
notifyAll()会把所有正在等待的线程全部唤醒,最终哪个线程能获得锁,由操作系统决定。 - 遇到中断
线程在阻塞状态,如果被中断了,则该线程会抛出中断异常并释放锁。
2.wait()和notify()的演示
/**
* Object类中的wait()、notify()的基本用法
*/
public class ThreadWaitNotify {
public static Object object = new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new DoWork1());
Thread thread2 = new Thread(new DoWork2());
thread1.start();
Thread.sleep(1000);
thread2.start();
}
}
class DoWork1 implements Runnable{
@Override
public void run() {
synchronized (ThreadWaitNotify.object){
System.out.println("线程1开始执行");
try {
// 释放锁,阻塞
ThreadWaitNotify.object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1重新获得锁");
}
}
}
class DoWork2 implements Runnable{
@Override
public void run() {
synchronized (ThreadWaitNotify.object){
ThreadWaitNotify.object.notify();
System.out.println("线程2调用notify()");
}
}
}
线程1中执行了wait()语句后即线程1进入等待状态,并且释放掉了锁,否则线程2无法进入synchronized的代码块。
3.notify()和notifyAll()的演示
/**
* Object类中的notify()、notifyAll()的基本用法
* 线程1、线程2阻塞,线程3负责唤醒他们
*/
public class ThreadWaitNotify {
public static Object resource = new Object();
public static void main(String[] args) throws InterruptedException {
DoWork1 doWork = new DoWork1();
DoWork3 doWork3 = new DoWork3();
Thread thread1 = new Thread(doWork);
Thread thread2 = new Thread(doWork);
Thread thread3 = new Thread(doWork3);
thread1.start();
thread2.start();
Thread.sleep(100);
thread3.start();
}
}
class DoWork1 implements Runnable{
@Override
public void run() {
synchronized (ThreadWaitNotify.resource){
System.out.println("线程["+Thread.currentThread().getName()+"]获得锁开始执行");
try {
// 释放锁,阻塞
System.out.println("线程["+Thread.currentThread().getName()+"]wait阻塞释放锁");
ThreadWaitNotify.resource.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程["+Thread.currentThread().getName()+"]重新获得锁");
}
}
}
class DoWork3 implements Runnable{
@Override
public void run() {
synchronized (ThreadWaitNotify.resource){
ThreadWaitNotify.resource.notifyAll();
System.out.println("线程["+Thread.currentThread().getName()+"]调用notify()");
}
}
}
如果把notifyAll()换成notify()呢?
线程0和线程1都在阻塞,而线程2只选择唤醒一个,那么应该剩余一个线程永远在阻塞了。
class DoWork3 implements Runnable{
@Override
public void run() {
synchronized (ThreadWaitNotify.resource){
ThreadWaitNotify.resource.notify();
System.out.println("线程["+Thread.currentThread().getName()+"]调用notify()唤醒一个线程");
}
}
}