是没有调用start方法 RUNNABLE,//可运行 表示当前线程可以运行,但实际是否运行有cpu决定 BLOCKED,//阻塞 其他线程获得锁,当前线程被阻塞在获得锁处 WAITING,//等待 等待其他条件成熟进入可运行状态 TIMED_WAITING,//计时等待 在一个指定时间内等待,超时后放弃 TERMINATED;//终止 线程执行完毕 }
线程的创建方式
Thread
继承Thread类:
class TestThread extends Thread{ @Override public void run() { super.run(); //do working } }
Runnable
实现Runnable接口:
static class TestRunnale implements Runnable{ @Override public void run() { //do working } } public static void main(String[] args) { TestRunnale runnale = new TestRunnale(); Thread thread = new Thread(runnale); thread.start(); }
线程的中断
不安全的中断
在Thread
的api中提供了一些终止线程的方法,比如stop()
,suspend()
,resume()
,但是这些方法目前在JDK中已经被标记位过时,因为这些方法具有死锁倾向,已经被明确表示不支持使用。
中断线程API
interrupt()
中断线程,本质是将线程的中断标志位设为true,其他线程向需要中断的线程打个招呼。是否真正进行中断由线程自己决定。
isInterrupted()
线程检查自己的中断标志位
静态方法
Thread.interrupted()
将中断标志位复位为false
中断标志位
自定义一个Boolean类型的中断标志位,提供一个中断方法,线程一直循环检测该标志位,标志位被设置为退出状态是终止线程。
public class FlagCancel { static class Flag extends Thread{ //中断标志 public static boolean flag = false; @Override public void run() { int i = 0; while(!flag){ System.out.println(i++); if(i>=3){ try { Thread.sleep(200); //interrupt(); if(i == 10) cancel();//修改中断状态,退出线程 System.out.println("thread:" + isInterrupted()); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("cancel..."); } } } public static void cancel(){ flag = true; } } public static void main(String[] args) { Flag test = new Flag(); test.start(); test.setPriority(10);//这里的设置优先级其实没什么用。cpu不会理你的。。。 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("main:" + test.isInterrupted());//这里属于主线程(main) } }
正常来说上面的形式没有什么问题,我们写代码的时候,提供一个修改中断为状态的方法,并根据我们自己的业务逻辑来定义什么时候中断,但是如果我们手动设置中断就有问题了,将上面代码中注释的interrupt();
打开。interrupt()
方法是用来中断线程的,但是在上面的逻辑中即使调用了该方法也不会立即中断,而必须要等待中断为被修改后才能退出。
安全的中断
上面介绍了中断相关的api和使用中断标志位来中断线程,但是中断标记位无法捕获异常情况。但是isInterrupted()
方法会一直检查线程的中断状态,所以我们可以用这个方法来实现安全的中断。
public class SafeInterrupt extends Thread { private boolean flag = false; @Override public void run() { int i = 0; System.out.println(Thread.currentThread().getName() + ":" +Thread.currentThread().isInterrupted()); while (!flag && !Thread.currentThread().isInterrupted()) { System.out.println(i++); try { synchronized (this) { if (i > 3) { //Thread.sleep(1000 * 60 * 60 * 24); wait(); } } } catch (InterruptedException e) { e.printStackTrace(); } } } /** * 这里必须将需要中断的线程作为参数传过来 * 用以进行中断 * @param t(Thread) */ public void cancel(Thread t) { System.out.println("ready stop currentThread..."); flag = true; //将需要中断的线程的中断标志位设置为true t.interrupt(); System.out.println(t.getName() + ":" + t.isInterrupted()); } public static void main(String[] args) throws InterruptedException { SafeInterrupt safeInterrupt = new SafeInterrupt(); safeInterrupt.start(); Thread.sleep(100); safeInterrupt.cancel(safeInterrupt); } }
不可中断的情况
好了,到现在我们已经可以安全的处理线程的中断了,但是还没完,因为不是所有的线程都是会响应中断的。比如IO的read()/write()
等就不会响应中断。而如果我们想不让其继续阻塞的话就需要我们手动的关闭底层的套接字。
public class CloseSocket extends Thread { private Socket socket; private InputStream in; public CloseSocket(Socket socket, InputStream in) { this.socket = socket; this.in = in; } //重写中断方法 在中断线程时中断套接字 @Override public void interrupt() { try { //关闭底层套接字 socket.close(); } catch (IOException e) { e.printStackTrace(); }finally { //中断线程 super.interrupt(); } } }
还有想死锁之类的不响应中断的情况用代码已经基本解决不了了,只能检查代码修改重启服务器啦。
共同學(xué)習(xí),寫下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章