线程停止与volatile
1.使用标志位停止线程
在Java中希望停止线程,可以使用设置标志位的方法,如下例所示:
class SimpleTask implements Runnable{
private boolean stop = false;
public void stop(){
stop = true;
}
@Override
public void run() {
while(!stop){
}
System.out.println("quit");
}
}
public class StopThreadTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
SimpleTask simpleTask = new SimpleTask();
executor.execute(simpleTask);
executor.shutdown();
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String word = sc.next();
if(word.equals("stop")){
System.out.println("stop the task");
simpleTask.stop();
}else if(word.equals("!"))
break;
}
}
}
然而无法成功停止线程。原因,没有同步,就不能保证后台线程何时“看到”main线程堆stop的值所做的改编。虚拟机将
while(!stop){}
//转化为
if(!stop)
while(true){}
改进,使用同步方法访问stop域。注意:读(getStop)写(stop)方法都要同步。
class SimpleTask implements Runnable{
private boolean stop = false;
public synchronized void stop(){
stop = true;
}
public synchronized boolean getStop(){
return stop;
}
@Override
public void run() {
while(!getStop()){
}
System.out.println("quit");
}
}
public class StopThreadTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
SimpleTask simpleTask = new SimpleTask();
executor.execute(simpleTask);
executor.shutdown();
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String word = sc.next();
if(word.equals("stop")){
System.out.println("stop the task");
simpleTask.stop();
}else if(word.equals("!"))
break;
}
}
}
使用volatile关键字可以获得一个更简洁、性能更好的版本
class SimpleTask implements Runnable{
private volatile boolean stop = false;
public void stop(){
stop = true;
}
@Override
public void run() {
while(!stop){
}
System.out.println("quit");
}
}
public class StopThreadTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
SimpleTask simpleTask = new SimpleTask();
executor.execute(simpleTask);
executor.shutdown();
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String word = sc.next();
if(word.equals("stop")){
System.out.println("stop the task");
simpleTask.stop();
}else if(word.equals("!"))
break;
}
}
}
原因:虽然volatile不执行互斥访问,但它可以保证任何一个线程(比如本例中的main线程)读取该域(stop)的时候都能看到最近刚刚被写入的值。
结论:
- 当多个线程共享可变数据的时候,每个读或者写数据的线程都必须执行同步(
synchronized
)。如果没有同步,就无法保证一个线程所做的修改可以被另一个线程获知。 - 如果需要线程之间的交互通信,而不需要互斥,
volatile
修饰符就是一种可以接收的同步形式。
参考:
Effective Java
2.使用线程的interrupt方法停止线程
原始链接:How can I kill a thread? without using stop();
public class HelloWorld {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new Runnable() {
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(5000);
System.out.println("Hello World!");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
thread.start();
System.out.println("press enter to quit");
System.in.read();
thread.interrupt();
}
}
使用这种方法停止线程的好处:Interrupting 可以让sleep()与wait()的线程直接被抛出异常,然后被终止。而不用等待其sleep完才能终止。
但也有不少人对这种方法提出质疑,认为这样终止线程比较危险。
总的来说使用第1种方法比较保守、安全。
线程停止与volatile的更多相关文章
- java线程学习之volatile关键字
volatile变量的主要作用:是使变量在多个线程间可见. 在java中每一个线程都会有一块工作内存区,其中存放着所有线程共享的主内存的变量值的拷贝.当线程执行时,它在自己的工作内存区操作这些变量,为 ...
- 注意!你的Thread.Abort方法真的让线程停止了吗?
大家都知道在C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Threa ...
- C# Thread.Abort方法真的让线程停止了吗?
大家都知道在C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Threa ...
- Java如何检查一个线程停止或没有?
Java如何检查一个线程停止或没有? 解决方法 下面的示例演示如何使用 isAlive()方法检查一个线程是否停止. public class Main { public static void ma ...
- EF Core使用SQL调用返回其他类型的查询 ASP.NET Core 2.0 使用NLog实现日志记录 CSS 3D transforms cSharp:use Activator.CreateInstance with an Interface? SqlHelper DBHelper C# Thread.Abort方法真的让线程停止了吗? 注意!你的Thread.Abort方法真
EF Core使用SQL调用返回其他类型的查询 假设你想要 SQL 本身编写,而不使用 LINQ. 需要运行 SQL 查询中返回实体对象之外的内容. 在 EF Core 中,执行该操作的另一种方法 ...
- (一)juc线程高级特性——volatile / CAS算法 / ConcurrentHashMap
1. volatile 关键字与内存可见性 原文地址: https://www.cnblogs.com/zjfjava/category/979088.html 内存可见性(Memory Visibi ...
- Java线程停止interrupt()方法
程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决,将导致意外的行为以及细微的.难以发现的错误.在本篇文章中,我们针对这些难题之一:如何中断一个正在运行的线程. 中 ...
- Thread的中断机制(interrupt),循环线程停止的方法
一.中断原理 中断线程 线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡.还是等待新的任务或是继续运行至下一步,就取决于这个 ...
- java多线线程停止正确方法
//军队线程 //模拟作战双方的行为 public class ArmyRunnable implements Runnable { //volatile保证了线程可以正确的读取其他线程写入的值 // ...
随机推荐
- POJ-2240 Arbitrage---判断正环+枚举
题目链接: https://vjudge.net/problem/POJ-2240 题目大意: 已知n种货币,以及m种货币汇率及方式,问能否通过货币转换,使得财富增加. 思路: 由于这里问的是财富有没 ...
- 新手创建Vue项目
======================安装vue=============================(参考网址:http://www.bubuko.com/infodetail-21320 ...
- js字符串操作总结
字符方法 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf- ...
- Unity中的基础光照
渲染包含了两大部分:决定一个像素的可见性,决定这个像素上的光照计算. 光照模型就是用于决定在一个像素上进行怎样的光照计算. 一.光源 在实时渲染中我们通常把光源当做一个没有体积的点. 1.1 辐照度 ...
- CSS3属性之圆角效果——border-radius属性
在css3之前,要实现圆角的效果可以通过图片或者用margin属性实现(可以参考这里:http://www.hicss.net/css-practise-of-image-round-box/).实现 ...
- [LeetCode] My Calendar II 我的日历之二
Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event w ...
- Python数据类型和数据操作
python数据类型有:int,float,string,boolean类型.其中string类型是不可变变量,用string定义的变量称为不可变变量,该变量的值不能修改. 下面介绍python中的l ...
- Shell自学二(参数传递和数组)
8.传递参数 1.使用$n来传递参数($0表示文件名) 例子: echo "执行的文件名:$0"; echo "第一个参数为:$1"; ...
- codevs 3061 质子撞击炮②
提交地址:http://codevs.cn/problem/3016/ 3016 质子撞击炮 II 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描 ...
- [ZJOI 2015]幻想乡战略游戏
Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...