笔者是广州的java程序员,刚毕业半年,工做之余写博客,若是以为个人文章写得不错,能够关注个人微信公众号(J2彬彬),里面会有更多精彩内容。从2018年8月份开始写博客,但愿往后写出更多通俗易懂的技术文章与你们一同分享。java
你有没有想过,如何中止一个线程?不少人首先会想到Thread.stop()方法,可是这个方法已通过时,不推荐使用,由于这个方法会带来安全问题,什么安全问题呢?后面会有详细说明。咱们先讲讲目前JDK API推荐使用中止线程的方法Thread.interrupt()方法。程序员
既然不能直接stop线程,那么只有一种方法可让线程结束,那就是让run方法运结束。 Thread.interrupt()表明的意思是“中止,停止”。可是这个方法须要加入一个判断才能够完成线程的中止。一旦检测到线程处于中断状态,那么就有机会结束run方法。 下面以一个代码示例看看它是如何中止线程的?安全
package com.bingo.thread.stopThread;
/** * Created with IntelliJ IDEA. * Description: 中止线程不推荐使用stop方法,此方法不安全,咱们可使用Thread.interrupt() * User: bingo */
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread.interrupt();
System.out.println("end...");
}
}
class MyThread extends Thread{
@Override
public void run() {
super.run();
for (int i = 0; i < 10000 ; i++) {
if(this.isInterrupted()){
System.out.println("已是中止状态了,我要退出了");
break;
}
System.out.println("i="+(i+1));
}
}
}
复制代码
运行结果:微信
i=1
......
i=3102
i=3103
i=3104
i=3105
i=3106
i=3107
i=3108
end...
已是中止状态了,我要退出了
复制代码
运行结果咱们能够看到,当myThread线程的循环运行到i=3108的时候,因为线程被中断,而跳出循环,这个例子很好诠释了interrupt方法的做用。多线程
package com.bingo.thread.stopThread;
/** * Created with IntelliJ IDEA. * Description: interrupt能够清除线程的冻结状态,让线程恢复到可运行的状态上来。 * User: bingo */
public class Run2 {
public static void main(String[] args) {
MyThread2 thread = new MyThread2();
thread.start();
thread.interrupt();
System.out.println("main end...");
}
}
class MyThread2 extends Thread{
@Override
public void run() {
System.out.println("run begin...");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
System.out.println("run 在沉睡中被停止,进入catch");
e.printStackTrace();
}
System.out.println("run end...");
}
}
复制代码
运行结果:ide
main end...
run begin...
run 在沉睡中被停止,进入catch
run end...
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.bingo.thread.stopThread.MyThread2.run(Run2.java:26)
复制代码
从运行结果咱们能够看到,原本run方法睡眠时间为1000秒,可是打印结果倒是瞬间的,其实sleep已经被interrupt方法给打断,此时线程冻结状态被清除,并抛出异常,被catch捕获,打印异常信息。学习
下图是JDK API对stop方法的描述,能够看到已过期,不推荐使用,并告诉咱们此方法为什么不安全? this
package com.bingo.thread.stopThread;
/** * Created with IntelliJ IDEA. * Description: stop()方法为什么不安全?下面例子可解答 * User: bingo */
public class StopTest {
public static void main(String[] args) {
try {
SynchrionzedObject object = new SynchrionzedObject();
MyThread3 t = new MyThread3(object);
t.start();
Thread.sleep(500);
t.stop();
System.out.println(object.getUsername()+" "+object.getPassword());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class SynchrionzedObject{
private String username = "a";
private String password = "aa";
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public synchronized void printString(String username,String password){
try {
this.username = username;
Thread.sleep(10000);
this.password = password;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyThread3 extends Thread{
private SynchrionzedObject object;
public MyThread3(SynchrionzedObject object){
this.object = object;
}
@Override
public void run() {
object.printString("b", "bb");
}
}
复制代码
运行结果:spa
b aa
复制代码
从上面例子咱们能够看到虽然printString方法加了锁,可是run方法运行过程当中忽然被stop了,锁被释放,MyThread线程只对username进行了赋值,而password赋值动做未执行,此时形成数据不一致。线程
其实java多线程不少方法内部都是native方法,也就是基于JVM内部实现的,因此咱们有必要结合JVM一块儿学习这部分的内容。技术的进步须要每一个小小的积累,才能走得更远,更长久。