1.中断线程:

  • 如果线程需要执行一个长时间任务,就可能需要中断线程。场景:从网络上下载一个100M的文件,用户在下载过程中中断下载任务的执行。
  • 中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法

1.1中断线程

需要检测isInterrupted()标志,其他线程通过调用interrupt()方法中断该线程

class HelloThread extends Thread{
public void run(){
while(!isInterrupted()){
System.out.println("Hello");
}
}
}
class Main{
public static void main(String[] args) throws Exception{
Thread t = new HelloThread();
t.start();
Thread.sleep(1000);
t.interrupt();
}
}

1.2中断等待状态的线程

如果线程处于等待状态,该线程会捕获InterruptedException。捕获到InterruptedException说明有其他线程对其调用了interrupt()方法,通常情况下该线程应该立即结束运行。

class HelloThread extends Thread{
public void run(){
while(!isInterrupted()){
System.out.println("Hello");
try{
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
return;
}
}
}
}

1.3设置running标志位中断线程

如果其他线程把HelloThread的标志位置设为false,while循环检测到running的值为false后,就会退出循环,结束run方法。

注意:线程间共享变量需要使用volatile关键字标记,确保线程能读取到更新后的变量值

class HelloThread extends Thread{
public volatile boolean running = true;
public void run(){
while(running){
System.out.println("Hello");
}
}
}
class Main{
public static void main(String[] args) throws Exception{
HelloThread t = new HelloThread();
t.start();
Thread.sleep(1000);
t.running = false;
}
}


问题:为什么要对线程间共享变量使用关键字volatile声明呢?
这涉及到Java的内存模型。在Java虚拟机中,变量的值保存在主内存中,但是当线程访问一个变量的时候,会先获取一个副本,并且保存自己的工作内存中。如果线程修改变量的值,虚拟机会在某个时刻把修改后的值回写到主内存,但是这个时间是不确定的。这会导致如果一个线程更新了某个变量,另一个线程读取的变量还是更新之前的。

如主内存中a的值是true。线程1执行时,先读取主内存中a的值(true),将a的值改写为false。但此时仅仅是线程1变量a的副本变为false,主内存中变量a还是true。
什么时候虚拟机将线程1修改后的值回写主内存,将a的值更新为false。这个时间是不确定的。
这时执行线程2,线程2读取的值可能仍然是true,而不是线程1更新后的false。

volatile关键字的目的是告诉虚拟机:

  • 每次访问变量时,总是获取主内存的最新值
  • 每次修改变量后,立刻回写到到主内存

volatile关键字解决的是可见性问题:

  • 当一个线程修改了某个共享变量的值,其他线程能够立刻看到修改后的值

2示例

2.1使用interrupt()中断线程

class InterrptThread extends Thread{
public void run(){
while(!isInterrupted()){
System.out.println("Hello");
try{
Thread.sleep(100);
}catch (InterruptedException ex){
System.out.println("Interrupted!");
break;
}
}
System.out.println("Thread end");
}
}
public class InterruptTest {
public static void main(String[] args) throws InterruptedException{
Thread t = new InterrptThread();
t.start();
Thread.sleep(1000);
t.interrupt();
System.out.println("main end");
}
}


### 2.2使用标志位中断线程
```#java
class InterrptThread extends Thread{
volatile boolean running = true;
public void run(){
while(running){
System.out.println("Hello");
try{
Thread.sleep(100);
}catch (InterruptedException ex){
System.out.println("Interrupted!");
break;
}
}
System.out.println("Thread end");
}
}
public class InterruptTest {
public static void main(String[] args) throws InterruptedException{
InterrptThread t = new InterrptThread();
t.start();
Thread.sleep(1000);
t.running = false;
System.out.println("main end");
}
}
```

3总结:

  • 调用interrupt()方法可以中断一个线程
  • 通过检测isInterrupted()标志获取当前线程是否已中断
  • 如果线程处于等待状态,该线程会捕获InterruptedException
  • isInterrupted()为true或者捕获了InterruptedException都应该立刻结束
  • 通过标志位判断需要正确使用volatile关键字
  • volatile关键字解决了共享变量在线程间的可见性问题

廖雪峰Java11多线程编程-1线程的概念-5中断线程的更多相关文章

  1. 廖雪峰Java11多线程编程-2线程同步-3死锁

    1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下 ...

  2. 廖雪峰Java11多线程编程-1线程的概念-1多线程简介

    多任务 现代操作系统(windows,MacOS,Linux)都可以执行多任务: 多任务就是同时运行多个任务,例如同时开启钉钉.百度网盘.火狐.谷歌.ps等 操作系统执行多任务就是让多个任务交替执行, ...

  3. 廖雪峰Java11多线程编程-2线程同步-4wait和notify

    wait和notify synchronized解决了多线程竞争的问题 我们可以在synchronized块中安全的对一个变量进行修改,但是它没有解决多线程协调的问题. 例如设计一个TaskQueue ...

  4. 廖雪峰Java11多线程编程-1线程的概念-2创建新线程

    Java语言内置多线程支持: 一个Java程序实际上是一个JVM进程 JVM用一个主线程来执行main()方法 在main()方法中又可以启动多个线程 1.创建新线程 1.1 方法一:使用Thread ...

  5. 廖雪峰Java11多线程编程-1线程的概念-3线程的状态

    1线程的状态 线程终止的的原因: run()或call()方法执行完成,线程正常结束 线程抛出一个未捕获的Exception或Error 直接调用该线程的stop()方法来结束该线程--该方法容易导致 ...

  6. 廖雪峰Java11多线程编程-3高级concurrent包-5Atomic

    Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int increm ...

  7. 廖雪峰Java11多线程编程-3高级concurrent包-4Concurrent集合

    Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等 ...

  8. 廖雪峰Java11多线程编程-3高级concurrent包-6ExecutorService

    Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配 ...

  9. 廖雪峰Java11多线程编程-3高级concurrent包-2ReadWriteLock

    ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共 ...

随机推荐

  1. 【转载】Abstract Factory Step by Step --- 抽象工厂

    抽象工厂是创建型模式的代表,其他的还有单件(Singleton).生成器(Builder).工厂方法(Factory Method)以及原型(Prototype),模式本身没有好坏之分,只有适用不适用 ...

  2. 0927CSP-S模拟测试赛后总结

    84pts rank28 经历了一个阶段的持续低迷,终于回到自己之前的位置了啊. 尽管依旧不是太靠上,但是还是证明了我的努力. 宿舍三人的风水轮流转之谈终究只是戏言和巧合.嘟嘟和Lockey都进第一机 ...

  3. hdu多校第三场 1006 (hdu6608) Fansblog Miller-Rabin素性检测

    题意: 给你一个1e9-1e14的质数P,让你找出这个质数的前一个质数Q,然后计算Q!mod P 题解: 1e14的数据范围pass掉一切素数筛法,考虑Miller-Rabin算法. 米勒拉宾算法是一 ...

  4. VS2010-MFC(Ribbon界面开发:创建Ribbon样式的应用程序框架)

    转自:http://www.jizhuomi.com/software/251.html 上一节讲了GDI对象之画刷CBrush,至此图形图像的入门知识就讲完了.从本节开始将为大家带来Ribbon界面 ...

  5. AtCoder ABC 129F Takahashi's Basics in Education and Learning

    题目链接:https://atcoder.jp/contests/abc129/tasks/abc129_f 题目大意 给定一个长度为 L ,首项为 A,公差为 B 的等差数列 S,将这 L 个数拼起 ...

  6. PAT甲级——A1135 Is It A Red-Black Tree 【30】

    There is a kind of balanced binary search tree named red-black tree in the data structure. It has th ...

  7. java-day06

    面向过程 每一个具体的步骤都亲力亲为,详细处理每一个细节 面向对象 不关心具体步骤,而是找一个已经具有该功能的人来帮我做事 特点 封装性 继承性 多态性 类 是一组相关属性和行为的集合 成员变量(属性 ...

  8. springcloud(十五):服务网关zuul

    前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个 ...

  9. Python学习之文件操作(二)

    CSV文件处理 在Python中处理CSV文件可以使用模块csv.有关csv模块的官方资料看这里. 1 读取csv文件 csv.reader(csvfile, dialect='excel', **f ...

  10. Java内存问题:java.lang.OutOfMemoryError: PermGen space

    代码运行环境: jdk1.7.0_25 apache-tomcat-8.0.30 详细报错日志: org.springframework.web.util.NestedServletException ...