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主动.被动关闭时发 ...
随机推荐
- lkx开发日志2-第一次团队讨论
遇到的问题 冰球与击球手碰撞的形式有两种.第一种:击球手的速度不指向冰球圆心,这样碰撞后冰球会旋转.第二种:击球手的速度指向冰球圆心,直接科运用动量定理计算两者速度的变化.考虑到时间限制,团队假设冰球 ...
- REmap首次尝试--PC端
在REchart项目中,实验此网址的内容,得到若干实例 针对此我针对北京市做了若干实验 第一:绘制北京市的填充地图 代码如下: >BJqu<-mapNames("beijing& ...
- python web前端
概述 HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏览器 ...
- (一)NOR FALSH 讲解
nor flash 起始地址: 1F FFFF = 1 1111 1111 1111 1111 1111 = 2^20 *2 = 2^21=2M Nor Flash 采用了 A0- ...
- java版模拟浏览器下载百度动漫图片到本地。
package javaNet.Instance.ImageDownload; import java.io.BufferedReader; import java.io.File; import j ...
- Extjs 3.4 同值合并
摘自:http://www.cnblogs.com/kunpengit/archive/2012/11/13/2768239.html/** * grid gridPanel 需要合并的表格 * ro ...
- paper 116:自然图像抠图/视频抠像技术梳理(image matting, video matting)
1. Bayesian Matting, Chuang, CVPR 2001.http://grail.cs.washington.edu/projects/digital-matting/paper ...
- HashSet的故事----Jdk源码解读
Hash,我们在说HashMap的时候,已经知道Hash是散列,Map是映射了. 那么Set又是什么呢 ? 先来看看Set的翻译是什么 n. [数] 集合:一套:布景:[机] 装置 这里Set所取的含 ...
- 快速排序算法 java 实现
快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...
- Hiho coder 1236 2015 北京网络赛 Score
五维偏序..一开始被吓到了,后来知道了一种BITSET分块的方法,感觉非常不错. 呆马: #include <iostream> #include <cstdio> #incl ...