Java - 安全的退出线程
stop() 存在的问题
使用 stop() 来退出线程是不安全的。它会解除由线程获取的所有锁,可能导致数据不一致。
举个例子:
public class StopTest { public static void main(String[] args) throws Exception { Person person = new Person(); person.setNameAndAge("Tom", 10); MyThread thread = new MyThread(person); thread.start(); Thread.sleep(500); thread.stop(); System.out.println(person.toString()); } } class MyThread extends Thread { Person person; public MyThread(Person person) { this.person = person; } @Override public void run() { person.setNameAndAge("Lin", 20); } } class Person{ private String name; private int age; public String getName() { return name; } public int getAge() { return age; } synchronized public void setNameAndAge(String name,int age){ this.name = name; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.age = age; } @Override public String toString() { return getName() + "," + getAge(); } }
打印输出:
Lin,10
按理说,setNameAndAge() 是一个同步方法,对象 person 总能保证对 name 和 age 同时赋值。因此上例中我们期待的输出应该是 “Lin,20”,由于调用的是 stop(),它会马上释放锁(即使正在同步块中),使得数据不一致。
所以要停止或退出线程,请忘记 stop()。
interrupt() 能退出线程吗?
public class InterruptTest { public static void main(String[] args) throws Exception { MyThread thread = new MyThread(); thread.start(); Thread.sleep(100); thread.interrupt(); } } class MyThread extends Thread { @Override public void run() { BufferedWriter writer = null; try { writer = new BufferedWriter(new FileWriter("C:/log.txt")); for (int i = 0; i < 5000000; i++) { String str = ""; if (i == 1) { str = i + ""; } else { str = "\n" + i; } writer.write(str); } } catch (Exception e) { e.printStackTrace(); } finally { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } }
可以看到输出的文件总行数为 500000,说明 interrupt() 并没有马上终止循环。
interrupt() 仅仅是在当前线程打了一个停止标记,并没有真的停止线程。
异常法退出线程
上代码:
public class Test { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } class MyThread extends Thread { @Override public void run(){ boolean flag = true; while (flag) { if (this.isInterrupted()) { System.out.println("线程即将停止"); try { throw new InterruptedException(); } catch (InterruptedException e) { flag = false; } } } System.out.println("已经跳出循环,线程停止"); } }
打印输出:
线程即将停止 已经跳出循环,线程停止
run 方法执行完,线程自然就结束了。
使用 return 退出线程
public class Test2 { public static void main(String[] args) { MyThread2 thread = new MyThread2(); thread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } } class MyThread2 extends Thread { @Override public void run() { while (true) { if (this.isInterrupted()) { System.out.println("线程停止"); return; } } } }
打印输出:
线程停止
Java - 安全的退出线程的更多相关文章
- Java线程监听,意外退出线程后自动重启
Java线程监听,意外退出线程后自动重启 某日,天朗气清,回公司,未到9点,刷微博,顿觉问题泛滥,惊恐万分! 前一天写了一个微博爬行程序,主要工作原理就是每隔2分钟爬行一次微博,获取某N个关注朋友微博 ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- Java多线程-新特性-线程池
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- Java笔记(二十)……线程间通信
概述 当需要多线程配合完成一项任务时,往往需要用到线程间通信,以确保任务的稳步快速运行 相关语句 wait():挂起线程,释放锁,相当于自动放弃了执行权限 notify():唤醒wait等待队列里的第 ...
- Java中的守护线程 & 非守护线程(简介)
Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- 初步探究java中程序退出、GC垃圾回收时,socket tcp连接的行为
初步探究java中程序退出.GC垃圾回收时,socket tcp连接的行为 今天在项目开发中需要用到socket tcp连接相关(作为tcp客户端),在思考中发觉需要理清socket主动.被动关闭时发 ...
随机推荐
- window虚拟机安装Linux
Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核.Linux可安装在各种计算机硬件设备中,比如手机.平板电脑.路由器.视频游戏控制台.台 ...
- GPS部标监控平台的架构设计(七)-压力测试
部标监控平台的压力测试是部标检测流程的最后一个检测环节,也是最难的,很多送检的企业平台都是卡壳在这一个环节.企业平台面临的问题如下: 1.对于压力测试的具体指标要求理解含糊,只知道是模拟一万辆车终端进 ...
- ActiveMQ 复杂类型的发布与订阅
很久没po文章了,但是看到.Net里关于ActiveMQ发送复杂类型的文章确实太少了,所以贴出来和大家分享 发布: //消息发布 public class Publisher { private IC ...
- Hosts文件
Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开, 其作用:就是将一些常用的网址域名与其对应的IP地址建立一个关联"数据库",当用户在浏览器中输入一个需要登录的网址时, ...
- hdu 1556
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- Linux Bond的原理及其不足
http://www.tektea.com/archives/1969.html. 在企业及电信Linux服务器环境上,网络配置都会使用Bonding技术做网口硬件层面的冗余,防止单个网口应用的单点故 ...
- Java多线程开发系列之番外篇:事件派发线程---EventDispatchThread
事件派发线程是java Swing开发中重要的知识点,在安卓app开发中,也是非常重要的一点.今天我们在多线程开发中,穿插进来这个线程.分别从线程的来由.原理和使用方法三个方面来学习事件派发线程. 一 ...
- lisp等
- ThinkPHP的异步搜索
因为公司的后台框架采用了Ajax异步处理,控制器的方法,有时候会被多个连接所重复调用,虽然这个很符合OOP开发思想,但是为了维护这个框架,付出的汗水也是很大的. 说下正题了: 我在后台的搜索框调用了优 ...
- HTTPS原理详解
HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTT ...