多线程之wait和notify

线程通信

两个线程间实现通信,如果轮询时间间隔小,浪费cpu资源,如果轮询时间间隔大,有可能会取到与期望值不一样的数据。

Wait 和 notify的实现

Wait方法是使当前执行代码的线程进行等待。但是在调用wait方法之前,线程必须获得该对象的对象级别锁。只能在同步方法或同步代码块中调用wait方法,在执行wait方法后,当前线程释放同步锁。同理notify方法也要在同步方法或同步代码块中调用。注意:当执行notify方法后,当前线程不会马上释放该对象,wait状态的线程也不会马上获取该对象锁,需要等执行notify方法的线程执行完(退出synchronized同步方法或同步代码块)。Wait方法在同步方法或同步代码块里运行,wait方法可以使调用该方法的线程释放同步对象锁。
Wait方法使线程停止,notify使停止的线程继续运行。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class ThreadA extends Thread{
private Object object;

public ThreadA(Object object) {
this.object = object;
}

@Override
public void run() {
synchronized (object){
System.out.println("wait开始,wait time="+System.currentTimeMillis());
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait结束,wait time="+System.currentTimeMillis());
}
}
}

public class ThreadB extends Thread {

private Object object;

public ThreadB(Object object) {
this.object = object;
}

@Override
public void run() {
synchronized (object){
System.out.println("notify开始,notify time="+System.currentTimeMillis());
object.notify();
System.out.println("notify结束,notify time="+System.currentTimeMillis());
}
}
}

public class Test {

public static void main(String[] args) {
Object object=new Object();
ThreadA threadA=new ThreadA(object);
threadA.start();
ThreadB threadB=new ThreadB(object);
threadB.start();
}
}

线程的生命周期

新建状态

当程序使用new创建一个线程后,就处于新建状态。

就绪状态(可运行状态)

当线程调用start()后,该线程就处于就绪状态,这是一个准备阶段

运行状态

如果线程抢到cpu资源,此线程就处于运行状态

阻塞状态

阻塞状态是线程因为某种原因放弃CPU使用权,使cpu处于空闲状态。

线程转化阻塞状态

  • 线程调用sleep方法,主动放弃占有的处理资源。
  • 线程调用了阻塞式IO已经返回,在该方法返回前,该线程被阻塞。
  • 线程试图获取一个同步监视器,但该同步监视器正被其他线程所持有。
  • 线程在等待某个通知。
  • 线程调用了suspend方法将该线程挂起。

阻塞状态重新进入就绪状态

因为线程运行一段时间后,有其他优先级高的线程抢占cpu
重新进入就绪状态有以下情况:

  • 调用sleep方法后经过的时间超过指定休眠时间。
  • 线程调用的阻塞IO已经返回,阻塞方法执行完毕。
  • 线程成功获取试图同步的监视器
  • 线程正在等待某个通知,其他线程发出了一个通知。
  • 处于挂起的线程调用了resume复方法
-------------本文结束感谢您的阅读-------------