线程停止与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保证了线程可以正确的读取其他线程写入的值 // ...
随机推荐
- Struts(二十六):文件上传
表单的准备 想要使用html表单上传一个或多个文件 1.须把html表单的enctype属性设置为multipart/form-data 2.须把html表单的method属性设置为post 3.须添 ...
- html标记语言 --图像标记
html标记语言 --图像标记 三.图像标记 1.使用方法 <img src="路径/文件名.格式" width="属性值" height="属 ...
- 合并css 合并图片 合并js
1:合并css 如:index.html 中的代码 <!DOCTYPE html><html lang="en"><head> <me ...
- innerHTML与innerText的区别
innerHTML获取元素的HTML内容,和设计元素的HTML内容(HTML标签会被解析)例如:ele.innerHTML="<strong>我会被解释加粗</strong ...
- 从让 HTTPS 更安全出发,聊聊 HTTPS
随着公众对网络安全的日益关注,各种网络安全防护手段层出不穷.HTTPS Everywhere作为提升HTTPS安全性的有效手段,日前安全性与实用性再次得到了加强. HTTPS虽然可以有效提升用户浏览网 ...
- [C#]Google Chrome 书签导出并生成 MHTML 文件
目的 因为某些原因需要将存放在 Google Chrome 内的书签导出到本地,所幸 Google Chrome 提供了导出书签的功能. 分析 首先在 Google Chrome 浏览器当中输入 ch ...
- jqgrid表格插件总结
jqgrid整了好多天,最重要得是理清思路,故做下记录,让大家少走弯路 1 配置环境,下载几个包导入(自行百度),从官网上下载一个案例导入,可以简单显示一个静态的画面(注意json包之间的兼容性) ...
- Error:ivalue require as left operant of assignment
Error:ivalue require as left operant of assignment 解答:该错误的意思是左操作数必须为左值,这个发生错误的原因在于赋值符号的左边不能是已确定的值,如: ...
- [HNOI2006]公路修建问题
题目描述 输入输出格式 输入格式: 在实际评测时,将只会有m-1行公路 输出格式: 输入输出样例 输入样例#1: 复制 4 2 5 1 2 6 5 1 3 3 1 2 3 9 4 2 4 6 1 3 ...
- UVA 1146 Now or later
The Terminal Radar Approach CONtrol (TRACON) controls aircraft approaching and departing when they a ...