多线程---停止线程
来源:互联网 发布:micro800编程软件下载 编辑:程序博客网 时间:2024/05/17 05:12
停止线程在java语言中并不像break,return那样干脆,需要一定的技巧性。
之前认为线程的停止很简单,一个interupt()方法就完成了,事实上这是完全错误的,线程的停止API中确实提供了一个简单的方法stop(),但是在新的API中已经被标记过时了,原因就是他不够安全。
在java中提供了2中方法用来终止正在运行的线程:
1)使用退出标志,使线程正常退出,也就是run()完成后线程终止
2)使用stop强行终止线程,但是不推荐,产生不可预料的后果
3)使用interrupt终止线程
- interrupt()并不能停止线程
可能我说了,你也不信,那就来个demo验证一下
public class A extends Thread { @Override public void run() { for(int j=0;j<50000;j++){ System.out.println("j="+j); } }}public static void main(String[] args) { A a = new A(); a.start(); try { Thread.sleep(2000); a.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println(e.toString()); } }
看一下打印结果:
没少打印吧,这就说明interrupt()并不能停止线程,调用interrupt()仅仅是在当前线程中打了一个停止标记,并不是真的停止线程。
- 正确判定线程的运行状态
想要正确的停止线程,必须要知道线程处于生命周期的什么时期,必须要了解这几个API.
1) interrupted();
2) isInterrupted();
先看一下这2个的介绍:
这里说的很清晰了,interrupted()测试当前线程是否中断,并且清除中断状态;isInterrupted()是测试线程是否已经中断,并不影响线程的状态;
下面来个demo说明一下:
public static void main(String[] args) { A a = new A(); a.start(); try { Thread.sleep(2000); a.interrupt(); System.out.println("interrupted:"+a.interrupted()); System.out.println("interrupted:"+a.interrupted()); System.out.println("is interrupted:"+a.isInterrupted()); System.out.println("is interrupted:"+a.isInterrupted()); } catch (InterruptedException e) { e.printStackTrace(); System.out.println(e.toString()); } }
打印结果
再来修改一下:
public static void main(String[] args) { A a = new A(); a.start(); try { Thread.sleep(2000); a.interrupt(); Thread.currentThread().interrupt(); System.out.println("interrupted:"+Thread.interrupted()); System.out.println("interrupted:"+Thread.interrupted()); System.out.println("is interrupted:"+a.isInterrupted()); System.out.println("is interrupted:"+a.isInterrupted()); } catch (InterruptedException e) { e.printStackTrace(); System.out.println(e.toString()); } }
再看一下打印:
这个结果就印证了API上对interrupted()的说明,是测试当前线程的状态,并清除中断状态。
分析:先看第一种情况,只是执行了a.interrupt(),虽然也执行了a.interrupted(),但是还是检测的当前线程,主线程(Main)一直没有中断,所以第一次的interrupted=false;
第二种情况:Thread.currentThread.interrupt()中断了主线程,所以第一次interrupted=true,由于他还有个作用清除当前线程的中断状态,所以第二次的时候interrupted=false;
在修改一下,看下isInterrupted
public class A extends Thread { @Override public void run() { for(int j=0;j<500000;j++){ System.out.println("j="+j); if(this.isInterrupted()){ System.out.println("is interrupted:"+this.isInterrupted()); System.out.println("is interrupted:"+this.isInterrupted()); break; } } }}public static void main(String[] args) { A a = new A(); a.start(); try { Thread.sleep(2000); a.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println(e.toString()); } }
看下打印结果:
这里看到isInterrupted()并不会清除线程的终止状态,所以2次都会true,虽然状态是ture,只是跳出了循环,但是线程仍然会运行。
- 异常法停止线程
有了前面的检测线程状态的API,就可以为线程的停止,提供依据
public class A extends Thread { @Override public void run() { try{ for(int j=0;j<500000;j++){ System.out.println("j="+j); if(this.isInterrupted()){ throw new InterruptedException("thread is interrupted"); } } System.out.println("for 之后运行"); //do some }catch(Exception e){ System.out.println(e.toString()); } }}public static void main(String[] args) { try { A a = new A(); a.start(); Thread.sleep(1000); a.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println(e.toString()); } }
看下打印结果
线程确实停止了,for语句后的也没有执行
return停止线程
将上面代码中的 throw new InterruptedException(“thread is interrupted”);改为return;也可以进行线程的终止,但是最好还是用异常法,因为catch块中的异常可以向上进行抛,使线程停止事件得以传播使用stop停止线程(不建议使用)
先看一下使用会有什么样的不良后果,
public class SynObject { private String name="a"; private String pwd="aaa"; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } synchronized public void printString(String name,String pwd){ try { this.name = name; Thread.sleep(100*1000); this.pwd = pwd; } catch (InterruptedException e) { e.printStackTrace(); } }}public class A extends Thread { private SynObject object; public A (SynObject object){ this.object = object; } @Override public void run() { object.printString("b", "bbb"); }} public static void main(String[] args) throws Exception { SynObject object = new SynObject(); A a = new A(object); a.start(); Thread.sleep(500); a.stop(); System.out.println("name:"+object.getName()+",pwd:"+object.getPwd()); }
这个逻辑很简单,object属性是有进行初始化的,printString对属性进行了重新赋值,看下结果
虽然线程是被及时停止了,但是获得的结果并不是我们预想的。stop()强行停止,可能使一些清理性的工作得不到完成,造成内存的泄漏;另外一个就是对锁定对象进行了“解锁”,导致数据得不到同步处理,出现数据不一致的问题;所以最好不要用
- b
- java 多线程 停止线程
- 多线程(停止线程)
- 多线程学习-停止线程
- 多线程(停止线程)
- JAVA-多线程-停止线程
- 多线程---停止线程
- java多线程 ---- 停止线程
- Java多线程-停止线程
- java多线程-停止线程interrupt
- 多线程提高、Lock、停止线程
- Java多线程 线程的停止
- java多线程之停止线程
- Java笔记 - 多线程 - 停止线程
- java多线程之-----停止线程
- Java多线程之停止线程
- Java多线程编程-停止线程 暂停线程
- 黑马程序员--多线程(三)之线程停止
- (笔记九)多线程、Lock、停止线程
- Git学习笔记
- 面试题:只能在UI线程里面更新界面吗?
- Android简易实战教程--第四十九话《满屏拖动的控件》
- CodeForces - 749C Voting 队列模拟
- ajax和jquery
- 多线程---停止线程
- 数值分析实验 Python
- bzoj 4568: [Scoi2016]幸运数字 倍增维护线性基
- shell脚本测试主机4个常见的网络服务是否开启
- MyEclipse中SVN用户名密码的切换
- commons-cli命令行参数解析
- Github下载单个文件夹
- 关于android中的事件分发机制,点击事件分发机制详解
- 百度地图