线程的状态
线程状态图(还是这张图)
进入runnable状态的条件
1:调用sleep方法后经过的时间超过了指定的休眠时间
2:线程调用的IO阻塞已经返回,阻塞方法执行完毕
3:线程调用的jion的线程执行完毕
4:正在运行running状态的线程主动调用yield方法放弃对CPU资源的占用
5:线程获得同步监视器
从running状态离开的条件
1:线程正常结束,或者异常终止
2:线程调用sleep方法,使得线程进入休眠状态
3:线程调用join方法,使得线程进入阻塞状态,等待join的线程运行完成
4:线程获得同步监视器失败
5:线程调用了wait方法,此时正在等待某个通知
6:调用阻塞IO方法
wait()方法
作用:
可以调用该方法的线程释放共享资源的锁,然后从running状态退出,进入等待队列,直到再次被唤醒。
注:
这是Object的方法,调用之后释放锁
notify()方法
作用:
可以随机唤醒等待队列中等待同一个共享资源的一个线程,并使得该线程退出等待队列,进入Runnable状态。
注:
这是Object的方法,调用之后不释放锁
notifyall()方法
作用:
可以使得所以正在等待队列等待同一个共享资源的线程都被唤醒,从等待队列退出,进入Runnable状态,此时优先级最高的线程首先进入Running状态,不过也可能是随机的,这取决于JVM的具体实现。
注:
这是Object的方法,调用之后不释放锁
示例代码:
package notifyTest;
class Service{
public void testMethod(Object lock) {
try {
synchronized(lock) {
System.out.println(" begin wait() ThreadName="+Thread.currentThread().getName());
lock.wait();
System.out.println(" end wait() ThreadName="+Thread.currentThread().getName());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 线程A
* */
class ThreadA extends Thread{
private Object lock;
public ThreadA(Object lock) {
this.lock=lock;
}
@Override
public void run() {
Service service=new Service();
service.testMethod(lock);
}
}
/**
* 线程B
* */
class ThreadB extends Thread{
private Object lock;
public ThreadB(Object lock) {
this.lock=lock;
}
@Override
public void run() {
Service service=new Service();
service.testMethod(lock);
}
}
/**
* 线程C
* */
class ThreadC extends Thread{
private Object lock;
public ThreadC(Object lock) {
this.lock=lock;
}
@Override
public void run() {
Service service=new Service();
service.testMethod(lock);
}
}
/**
* 通知线程
* */
class NotifyThread extends Thread{
private Object lock;
public NotifyThread (Object lock) {
this.lock=lock;
}
@Override
public void run() {
synchronized (lock) {
lock.notify();//随机唤醒等待队列中等待同一个共享资源的线程
//lock.notifyAll();//唤醒等待队列中所有等待同一个共享资源的线程
}
}
}
public class Main {
public static void main(String[]args) {
try {
Object lock=new Object();
ThreadA threada=new ThreadA(lock);
ThreadB threadb=new ThreadB(lock);
ThreadC threadc=new ThreadC(lock);
threada.start();
threadb.start();
threadc.start();
/**
* 以上是启动3个线程
*
* 下面启动通知线程
* */
Thread.sleep(10);
NotifyThread notifyThread=new NotifyThread(lock);
//此时启动的四个线程都在使用同一个共享资源
notifyThread.start();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
begin wait() ThreadName=Thread-2
begin wait() ThreadName=Thread-1
begin wait() ThreadName=Thread-0
end wait() ThreadName=Thread-2
结果分析
此时,NotifyThread线程只调用了notify方法,所以从等待队列中随机唤醒一个等待同一个共享资源的线程。
稍作修改,调用notifyAll()方法
/**
* 通知线程
* */
class NotifyThread extends Thread{
private Object lock;
public NotifyThread (Object lock) {
this.lock=lock;
}
@Override
public void run() {
synchronized (lock) {
//lock.notify();//随机唤醒等待队列中等待同一个共享资源的线程
lock.notifyAll();//唤醒等待队列中所有等待同一个共享资源的线程
}
}
}
运行结果:
begin wait() ThreadName=Thread-0
begin wait() ThreadName=Thread-2
begin wait() ThreadName=Thread-1
end wait() ThreadName=Thread-1
end wait() ThreadName=Thread-2
end wait() ThreadName=Thread-0
结果分析:
此时,等待队列中有三个使用同一个共享资源的线程,notifyAll会将他们全都唤醒。