首先说明,使用stop方法终止的方式已经在很久之前就被废弃了,在加锁的情况下有可能会造成死锁,这里不做讨论。

1. 使用标志位终止线程

在run()方法执行完毕后,该线程就终止了。但是在某些特殊的情况下,希望run()方法中的代码一直循环执行。比如在服务端程序中可能会使用 while(true) { ... } 这样的循环结构来不断的接收来自客户端的请求。此时就可以用修改标志位的方式来结束 run() 方法。例:

  1. public class ServerThread extends Thread {
  2. //volatile修饰符用来保证其它线程读取的总是该变量的最新的值
  3. public volatile boolean exit = false;
  4.  
  5. @Override
  6. public void run() {
  7. ServerSocket serverSocket = new ServerSocket(8080);
  8. while(!exit){
  9. serverSocket.accept(); //阻塞等待客户端消息
  10. ...
  11. }
  12. }
  13.  
  14. public static void main(String[] args) {
  15. ServerThread t = new ServerThread();
  16. t.start();
  17. ...
  18. t.exit = true; //修改标志位,退出线程
  19. }
  20. }

Note:一定要给标志位加上volatle 关键字!详细原因可参考:https://www.cnblogs.com/yongdaimi/p/9566332.html 或者 https://www.cnblogs.com/dolphin0520/p/3920373.html 。

2. 使用interrupt()方法来终止线程

interrupt()方法用于中断线程,调用该方法的线程状态将会被置为“中断状态”。
Note: 线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。java中的那些支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。

调用这种方式去终止的线程存在两种情况:

第一种情况:该线程循环执行不会存在阻塞
比如,在while 循环中循环打印一句话:这样的话调用interrupt()会立即终止该线程。例:

  1. package com.yongdaimi.java.demo;
  2.  
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.ReentrantLock;
  5.  
  6. public class Test3 {
  7.  
  8. public static void main(String[] args) {
  9. NotInterruptThread mNotInterruptThread = new NotInterruptThread();
  10. mNotInterruptThread.start();
  11.  
  12. try {
  13. Thread.sleep(5000);
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. }
  17.  
  18. mNotInterruptThread.interrupt();
  19. }
  20.  
  21. static class NotInterruptThread extends Thread {
  22. @Override
  23. public void run() {
  24. super.run();
  25. while (!isInterrupted()) {
  26. System.out.println("=============NotInterruptThread execute... =============");
  27. }
  28. }
  29.  
  30. }
  31.  
  32. }

运行结果:

=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
=============NotInterruptThread execute... =============
5 秒后,打印就会停止。

第二种情况:该线程循环执行存在阻塞状态
比如,在线程中存在sleep()、await()、wait(long) 这种能够抛出:interruptedException 异常的方法,这种情况调用interrupt()方法后将会触发这些异常,可以选择在触发异常后调用break来终止线程。例:

  1. package com.yongdaimi.java.demo;
  2.  
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.ReentrantLock;
  5.  
  6. public class Test3 {
  7.  
  8. private static Object sLock = new Object();
  9.  
  10. private static ReentrantLock sReentrantLock = new ReentrantLock();
  11. private static Condition sSuspendCondition = sReentrantLock.newCondition();
  12.  
  13. public static void main(String[] args) {
  14. /*NotInterruptThread mNotInterruptThread = new NotInterruptThread();
  15. mNotInterruptThread.start();
  16.  
  17. try {
  18. Thread.sleep(5000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22.  
  23. mNotInterruptThread.interrupt();
  24. */
  25.  
  26. InterruptThread interruptThread = new InterruptThread();
  27. interruptThread.start();
  28.  
  29. try {
  30. Thread.sleep(6000);
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34.  
  35. interruptThread.interrupt();
  36.  
  37. /*InterruptThread1 interruptThread1 = new InterruptThread1();
  38. interruptThread1.start();
  39.  
  40. try {
  41. Thread.sleep(5000);
  42. } catch (InterruptedException e) {
  43. e.printStackTrace();
  44. }
  45.  
  46. interruptThread1.interrupt();*/
  47.  
  48. /*InterruptThread2 interruptThread2 = new InterruptThread2();
  49. interruptThread2.start();
  50.  
  51. try {
  52. Thread.sleep(3000);
  53. } catch (InterruptedException e1) {
  54. e1.printStackTrace();
  55. }
  56.  
  57. interruptThread2.interrupt();*/
  58.  
  59. /*sReentrantLock.lock();
  60. try {
  61. sSuspendCondition.signal();
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. } finally {
  65. sReentrantLock.unlock();
  66. }*/
  67.  
  68. }
  69.  
  70. static class NotInterruptThread extends Thread {
  71. @Override
  72. public void run() {
  73. super.run();
  74. while (!isInterrupted()) {
  75. System.out.println("=============NotInterruptThread execute... =============");
  76. }
  77. }
  78.  
  79. }
  80.  
  81. static class InterruptThread extends Thread {
  82.  
  83. @Override
  84. public void run() {
  85. super.run();
  86. while (!isInterrupted()) {
  87. System.out.println("=============InterruptThread execute... =============");
  88. try {
  89. Thread.sleep(50000);
  90. } catch (InterruptedException e) {
  91. e.printStackTrace();
  92. break;
  93. }
  94. }
  95. }
  96. }
  97.  
  98. static class InterruptThread1 extends Thread {
  99.  
  100. @Override
  101. public void run() {
  102. super.run();
  103. while (!isInterrupted()) {
  104. synchronized (sLock) {
  105. System.out.println("=============InterruptThread execute... =============");
  106. try {
  107. sLock.wait();
  108. } catch (InterruptedException e) {
  109. e.printStackTrace();
  110. break;
  111. }
  112. }
  113. }
  114. }
  115. }
  116.  
  117. static class InterruptThread2 extends Thread {
  118.  
  119. @Override
  120. public void run() {
  121. super.run();
  122. while (!isInterrupted()) {
  123. sReentrantLock.lock();
  124. try {
  125. System.out.println("=============InterruptThread execute... =============");
  126. sSuspendCondition.await();
  127. } catch (InterruptedException e) {
  128. e.printStackTrace();
  129. break;
  130. } finally {
  131. sReentrantLock.unlock();
  132. }
  133. }
  134. }
  135. }
  136.  
  137. }

我这里分别演示了使用sleep()、wait()、await()的方式来阻塞线程,然后在主线程休眠一段时间后尝试去中断,子线程中收到异常后调用break退出循环,实际试验都可以正常退出循环。

参考链接:

1. interrupt、interrupted 、isInterrupted 区别

2. Java终止线程的三种方法

Java: Java终止线程的几种方式的更多相关文章

  1. java中终止线程的三种方式

    在java中有三种方式可以终止线程.分别为: 1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止.  2.  使用stop方法强行终止线程(这个方法不推荐使用,因为stop和sus ...

  2. Java中终止线程的三种方法

    终止线程一般建议采用的方法是让线程自行结束,进入Dead(死亡)状态,就是执行完run()方法.即如果想要停止一个线程的执行,就要提供某种方式让线程能够自动结束run()方法的执行.比如设置一个标志来 ...

  3. Java中创建线程的两种方式

    创建线程的第一种方式: 创建一个类继承Thread 重写Thread中的run方法 (创建线程是为了执行任务 任务代码必须有存储位置,run方法就是任务代码的存储位置.) 创建子类对象,其实就是在创建 ...

  4. Java终止线程的三种方式

    停止一个线程通常意味着在线程处理任务完成之前停掉正在做的操作,也就是放弃当前的操作. 在 Java 中有以下 3 种方法可以终止正在运行的线程: 使用退出标志,使线程正常退出,也就是当 run() 方 ...

  5. Java值创建线程的两种方式对比

    在Java中创建线程的方式有两种,第一种是直接继承Thead类,另一种是实现Runable接口.那么这两种方式孰优孰劣呢? 采用继承Thead类实现多线程: 优势:编写简单,如果需要访问当前线程,只需 ...

  6. Java 多线程 创建线程的4种方式

    1 继承Thread类,重写run方法.Thread类实现了Runnable接口. 2 实现Runnable接口,重写run方法.相比于继承Thread类,可以避免单继承的缺陷和实现资源共享. 举例: ...

  7. Java中创建线程的三种方式以及区别

    在java中如果要创建线程的话,一般有3种方法: 继承Thread类: 实现Runnable接口: 使用Callable和Future创建线程. 1. 继承Thread类 继承Thread类的话,必须 ...

  8. Java多线程——创建线程的两种方式

    创建线程方式一:继承Thread类. 步骤:1,定义一个类继承Thread类.2,覆盖Thread类中的run方法.3,直接创建Thread的子类对象创建线程.4,调用start方法开启线程并调用线程 ...

  9. Java中创建线程的三种方式及其优缺点

    1.自定义一个继承Thread的类,由于Java的单继承特性,限制了该类的扩展性. 2.实现Runnable接口,重写run()方法. 3.实现Callable接口,重写call方法.线程执行体可以有 ...

随机推荐

  1. mysql-luster没有data目录

    mysqld --initialize-insecure --user=mysql 直接复制上面这条命令 然后cmd进入到 mysql解压出来bin的目录中: 等待一会  就发发现data的这个目录了 ...

  2. redis-Jedis连接集群

    关闭防火墙或把端口加入防火墙 一.通过代码 @Test public void testJedisCluster() throws Exception { //创建一连接,JedisCluster对象 ...

  3. docker配置镜像加速器

    docker配置镜像加速器 针对Docker客户端版本大于 1.10.0 的用户 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器 sudo mkdir - ...

  4. Kudu+Impala介绍

    Kudu+Impala介绍 概述 Kudu和Impala均是Cloudera贡献给Apache基金会的顶级项目.Kudu作为底层存储,在支持高并发低延迟kv查询的同时,还保持良好的Scan性能,该特性 ...

  5. js 正则表达式 贪婪与惰性

    首先引入一个介绍比较详细的网站 http://www.jb51.net/article/31491.htm 接下来是本人的简介 其实贪婪和惰性很容易理解,从字面意思我们就可以知道,所谓的"贪 ...

  6. url 组成

  7. docker, docker-compose安装和使用

    官方文档: 安装docker: https://docs.docker.com/install/linux/docker-ce/centos/ 安装docker-compose: https://do ...

  8. hdu1540-Tunnel Warfare-(线段树+二分)

    题意:有n个村庄排成一列,相邻的村庄可以通信,炸毁则不可以通信,进行m个操作.3种操作,1.炸毁某村庄:2.修复上一个被炸毁的村庄:3.查询某个村庄能通信的村庄数(自己算一个). 解题:求某个点左边扩 ...

  9. QQ互联登陆(Java)

    一.准备部分 1.账户注册 腾讯开放平台网址: https://connect.qq.com/index.html 首先需要到开放平台注册QQ互联开发者身份.注册之后创建一个网站应用,注意,需要备案成 ...

  10. 01_搭建基本的FTP服务器(数通华为)

    1.选择客户端和服务端: 2.FTP服务端配置设置待FTP的文件: 3.客户端配置访问: 4.双击下载到本地: