线程状态
在java.lang.Thread.State定交了6个状态:
- New:尚未启动的线程的线程状态。
- Runnable:可运行线程的线程状态,等待CPU调度。
- Blocked:线程阻塞等待监视器锁定的线程态。处于synchronized同步代码块或方法中被阻塞。
- Waiting:等待线程的线程状态。下列不带超时的方式:Object.wait、Thread.join、LockSupport.park
- Timed Waiting:具有指定等待时间的等待线程的线程状态。下列带超时的方法thread.sleep、Object.wait(long timeout)、Thread.join、LockSupport.parkNanos、LockSupport.parkUntil
- Terminated:终止线程的线程状态。线程正常完成执行或者出现异常。
以下是线程状态切换图:
接着上一段代码,演示一下各种状态的切换效果:
public class Demo2 {
//public static Thread thread1;
public static void main(String[] args) throws InterruptedException {
System.out.println("第一种:新建 -> 运行 -> 终止");
Thread thread1 = new Thread(new Runnable() {
public void run() {
System.out.println("thread1状态:"+Thread.currentThread().getState().toString());
System.out.println("thread1执行了");
}
});
System.out.println("start方法前:"+thread1.getState().toString());
thread1.start();
thread1.sleep(2000L);
System.out.println("start方法后:"+thread1.getState().toString());
// thread1.start(); TODO 注意:线程终止后,再运行调用start(),会抛出IllegalThreadStateException异常
System.out.println("第二种:新建 -> 运行 -> 等待 -> 运行-> 终止");
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread2状态:"+Thread.currentThread().getState().toString());
System.out.println("thread2执行了");
}
});
System.out.println("thread2 start方法前:"+thread2.getState().toString());
thread2.start();
System.out.println("thread2 start方法后:"+thread2.getState().toString());
thread2.sleep(200L);
System.out.println("thread2 等待200毫秒后:"+thread2.getState().toString());
thread2.sleep(3000L);
System.out.println("thread2 等待3秒后:"+thread2.getState().toString());
System.out.println("第三种:新建 -> 运行 -> 堵塞 -> 运行-> 终止");
Thread thread3 = new Thread(new Runnable() {
public void run() {
synchronized(Demo2.class) {
System.out.println("thread3 状态:"+Thread.currentThread().getState().toString());
System.out.println("thread3 执行了");
}
}
});
synchronized (Demo2.class) {
System.out.println("thread3 start前:"+ thread3.getState().toString());
thread3.start();
System.out.println("thread3 start后:"+ thread3.getState().toString());
Thread.sleep(200);
System.out.println("thread3 等待200毫秒后:"+thread3.getState().toString());
}
Thread.sleep(3000);
System.out.println("thread3 等待3秒后:"+thread3.getState().toString());
}
}
运行结果如下:
第一种:新建 -> 运行 -> 终止
start方法前:NEW
thread1状态:RUNNABLE
thread1执行了
start方法后:TERMINATED
第二种:新建 -> 运行 -> 等待 -> 运行-> 终止
thread2 start方法前:NEW
thread2 start方法后:RUNNABLE
thread2 等待200毫秒后:TIMED_WAITING
thread2状态:RUNNABLE
thread2执行了
thread2 等待3秒后:TERMINATED
第三种:新建 -> 运行 -> 堵塞 -> 运行-> 终止
thread3 start前:NEW
thread3 start后:RUNNABLE
thread3 等待200毫秒后:BLOCKED
thread3 状态:RUNNABLE
thread3 执行了
thread3 等待3秒后:TERMINATED
其中:synchronized(Demo2.class),表示去拿主线程的一把锁。如果该锁已经被其他代码争抢了,则在去取这把锁的时候将进入阻塞状态。直到这把锁被释放后,争抢成功才会进入下步的执行动作。
线程中止
不正确的线程中止-Stop
Stop:中止线程,并且清除监控器锁的信息,但是可能导致线程安全问题,JDK不建议用。
Destory:JDK未实现该方法。
以下有两段代码:
StopThread.java
public class StopThread extends Thread{
private int i=0,j=0;
@Override
public void run() {
synchronized (this) {
++i;
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
++j;
}
}
public void print() {
System.out.println("i="+i+",j="+j);
}
}
Demo3.java
public class Demo3 {
public static void main(String[] args) throws InterruptedException {
StopThread thread=new StopThread();
thread.start();
Thread.sleep(1000);
thread.stop();
while(thread.isAlive()) {
//保证线程已经中止
}
thread.print();
}
}
其中synchronized (this)代码块的用意是保证synchronized块内代码执行代码的线程安全,不受其它线程影响。
但stop,强行中止了线程。造成结果是:
i=1,j=0
正确的线程中止- interrupt
如果目标线程在调用Object class的wait()、wait(long)或wait(long,int)方法、join()、join(long,int)或sleep(long,int),方法时被阻塞,那么Interrupt会生效,该线程的中断状态将被清除,抛出InterruptedException异常。
如果目标线程是被I/O或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。
如果以上条件都不满足,则会设置此线程的中断状态。
如果将刚才Demo3中的stop改为interrupt
运行结果如下:
我们可以看到,运行的结果除了i=1,j=1
使用interrupt去中上线程,java会以一种异常的方式通知开发人员,由开发人员去处理这个异常。从而保证了线程安全。
正确的线程中止- 标志位
代码逻辑中,增加一个判断,用来控制线程的中止。
public class Demo4 extends Thread{
public volatile static boolean flag=true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
try {
while(flag) {
System.out.println("运行中");
Thread.sleep(1000);
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(3000);
flag=false;
System.out.println("程序运行结束");
}
}
执行结果如下:
运行中
运行中
运行中
程序运行结束