Thread类:
sleep:暂停当前正在执行的线程;
Object类:
wait:暂停当前正在执行的线程,直到调用notify()或notifyAll()方法或超时,退出等待状态;
notify:唤醒在该对象上等待的一个线程;
sleep,wait,notify的使用
public static void main(String[] args) {
final Object o = new Object();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (o) {
try {
System.out.println("等待唤醒前");
//wait(): 哪个线程执行这行代码,这个线程就等待
o.wait();
System.out.println("等待唤醒后");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (o) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("唤醒操作");
//notify(): 唤醒正在等待的线程
o.notify();
}
}
}).start();
}
1.wait和notify要在同步代码块中使用
2.wait和notify必须共用一把锁,才知道需要唤醒的是谁
3.任何对象都可以作为锁,所以wait和notify方法在java源码的设计时放在了Object类中
4.sleep不会将锁还回去,wait会把锁还回去(原因是wait要把锁交给notify)
5.wait和notify的主要作用是线程之间的通信,是以后rabbitmq等框架中消息队列的基础原理,最典型的案例就是生产者消费者问题
生产者与消费者
/**
*生产者
*/
public class BaoZiPu implements Runnable {
private ArrayList<String> list;
public BaoZiPu(ArrayList<String> list) {
this.list = list;
}
@Override
public void run() {
System.out.println("包子铺启动了...");
int num = 1;
while (true) { // 循环来生成包子
synchronized (list) {
// 1.如果有包子就等待
if (list.size() > 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 2.如果没有包子就生成一个包子,通知吃货线程
String baoZi = "包子" + num;
num++;
list.add(baoZi);
System.out.println("包子铺生成一个包子: " + list);
list.notify();
}
}
}
}
/**
*消费者
*/
public class ChiHuo implements Runnable {
private ArrayList<String> list;
public ChiHuo(ArrayList<String> list) {
this.list = list;
}
@Override
public void run() {
System.out.println("吃货启动了...");
while (true) { // 循环吃包子
synchronized (list) {
// 1.如果没有包子就等待
if (list.size() == 0) {
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 2.如果有包子就吃包子,通知包子铺
String baozi = list.remove(0);
System.out.println("吃货吃了一个包子: " + baozi);
list.notify();
}
}
}
}
/**
*主线程
*/
public static void main(String[] args) {
// 创建包子容器
ArrayList<String> list = new ArrayList<>();
new Thread(new BaoZiPu(list)).start();
new Thread(new ChiHuo(list)).start();
}
线程状态转换图
依据:public static enum Thread.State extends Enum<Thread.State>
线程可以处于以下状态之一:
NEW尚未启动的线程处于此状态。
RUNNABLE在Java虚拟机中执行的线程处于此状态。
BLOCKED被阻塞等待监视器锁定的线程处于此状态。
WAITING正在等待另一个线程执行特定动作的线程处于此状态。
TIMED_WAITING正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
TERMINATED已退出的线程处于此状态。
一个线程可以在给定时间点处于一个状态。 这些状态是不反映任何操作系统线程状态的虚拟机状态。