一、线程生命周期
JDK中用Thread.State类枚举定义了线程的几种状态,如下:
NEW:新建
RUNNABLE:运行
BLOCKED:阻塞,一个正在执行的线程在某些特殊情况下,如执行耗时的输入/输出操作时,会放弃CPU 的使用权,进入阻塞状态;
WAITING:进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断);处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态;
TIMED_WAITING:该状态不同于WAITING,它可以在指定的时间后自行返回;
TREMINATED:正常结束、提前终止、或异常而结束;
二、状态分析
1、运行、阻塞状态情况:
public class Test2 extends Thread{ private int i = 0; @Override public void run() { long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < 2) { System.out.println(Thread.currentThread().getName() + ": is running"); //thread1执行addNum时,其它thread处于等待锁,BLOCKED状态 addNum(); } } private void addNum() { synchronized (this) { System.out.println("当前执行线程:"+Thread.currentThread()); i ++; } } public static void main(String[] args) throws InterruptedException { //NEW Test2 test1 = new Test2(); Test2 test2 = new Test2(); Test2 test3 = new Test2(); //RUNNABLE test1.start(); //等待线程test1结束,此时test2处于waiting状态 test1.join();//wait() //启动test2 test2.start(); //Thread.sleep(long millis),一定是当前线程调用此方法,当前主线程进入TIMED_WAITING状态 Thread.sleep(200);//200ms后自动苏醒 } }
2、wati状态,notify唤醒使用
2.1 wait和notify必须配合synchronized关键字使用。
2.2wait方法释放锁,notify方法不释放锁。
2.3 还要注意一点 就是涉及到线程之间的通信,就肯定会用到validate修饰。
package com.example.demo.threadimpl;
import java.util.ArrayList;
import java.util.List;
/**
* wait和notify的使用
*
* @author Administrator
*
*/
public class MyThread004 {
private static volatile List list=new ArrayList();
public void add() {
list.add("demo");
}
public int size() {
return list.size();
}
public static void main(String[] args) {
MyThread004 list1=new MyThread004();
Object obj=new Object();
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
synchronized (obj) {
System.out.println("t1线程启动。。。。");
for(int i=0;i<10;i++) {
list1.add();
System.out.println("当前线程"+Thread.currentThread().getName()+"添加了一个元素");
try {
Thread.sleep(500);
if(list1.size()==5) {
System.out.println("已经发出通知。。");
obj.notify();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"t1");
Thread t2=new Thread (new Runnable() {
@Override
public void run() {
synchronized (obj) {
System.out.println("t2启动。。。");
if(list1.size()!=5) {
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
throw new RuntimeException();
}
}
},"t2");
t2.start();
t1.start();
}
}
仔细观察代码,wait、notify必须结和关键字synchronize。优先启动t2线程,使t2在run方法中进入wait,然后启动t1,t1执行过程中唤醒被sync的obj对象,使得t2等待资源,一旦t1执行完,释放资源后,t2就继续执行了。
注意:t2进入wait状态后,必须被唤醒才会继续往下执行代码的。
3.盗用逻辑状态图片如下