博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中停止线程执行的方法
阅读量:5956 次
发布时间:2019-06-19

本文共 3172 字,大约阅读时间需要 10 分钟。

Java中停止线程执行的方法
一、暂停或停止线程的理论
在Java编程中,要暂停或停止当前正在运行的线程,有几种方法。对于把线程转入睡眠Sleep状态,使用Thread.sleep()是最正确的方式。或许有人会问,为什么不使用等待wait()或通知notify()?要知道,使用等待或通知都不是很好的方式。
线程可以使用等待wait()实现被阻塞,这属于条件等待的方式,当条件满足后,又会从阻塞转为等待状态。尽管可以在等待wait()条件那里放一个超时设置,但等待wait()的设计目的不是这样的,等待wait()在设计上是用于Java线程间的通信。
而使用睡眠sleep()方式,可以让线程从当前开始睡眠指定的时间。注意不要使用睡眠sleep()方式去代替等待wait()或通知notify(),反之亦然。
Java线程通信的例子: http://javarevisited.blogspot.sg/2013/12/inter-thread-communication-in-java-wait-notify-example.html
等待wait()或通知notify()不应该用于暂停线程,还有一个原因,等待wait()或通知notify()需要一个锁。只能从一个同步的方法或同步的代码块去调用它们,获取锁和释放锁的开销是比较大的。而且,只是暂停线程的话,无需引入锁机制。
sleep()与wait()还有一点不同,sleep()会把当前的线程转入等待状态,它不会释放它持有的任何锁,而wait()使得线程转入阻塞状态,会释放掉自己持有的锁。
总之,Java多线程编程并不简单,即使是简单的任务,如创建线程、停止线程或暂停线程,都需要认真掌握Java API。
二、暂停或停止线程的实战
下面的例子中,要暂停线程,可以使用Thread.sleep()或TimeUnit.sleep()方法。例子中,有两个线程,主线程由JVM启动,它执行main()方法。第二个线程叫T1,它由主线程创建,用于循环运行游戏。我们传递的Runnable任务是一个无限循环,会一直运行直到我们停止它。注意看,我使用了volatile关键字。
主线程首先启动T1线程,再使用stop()方法停止线程。
在这个例子中,我们有两种方法停止线程的运行,使用Thread.sleep()方法或者是使用TimeUnit.sleep()方法。TimeUnit类既可以指定秒即TimeUnit.SECONDS,又可以指定毫秒即TimeUnit.MILLISECONDS。总的来说,使用TimeUnit的sleep()方法,使得代码更为易读。

点击(此处)折叠或打开

  1. import static java.lang.Thread.currentThread;
  2. import java.util.concurrent.TimeUnit;
  3. public class ThreadPauseDemo{
  4.     public static void main(String args[]) throws InterruptedException {
  5.         Game game = new Game();
  6.         Thread t1 = new Thread(game, "T1");
  7.         t1.start();
  8.         // 现在停止Game线程
  9.         System.out.println(currentThread().getName() + " is stopping game thread");
  10.         game.stop();
  11.         // 查看Game线程停止的状态
  12.         TimeUnit.MILLISECONDS.sleep(200);
  13.         System.out.println(currentThread().getName() + " is finished now");
  14.     }
  15. }

点击(此处)折叠或打开

  1. class Game implements Runnable{
  2.     private volatile boolean isStopped = false;
  3.     public void run(){
  4.         while(!isStopped){
  5.             System.out.println("Game thread is running......");
  6.             System.out.println("Game thread is now going to pause");
  7.             try{
  8.                 Thread.sleep(200);
  9.             } catch(InterruptedException e){
  10.                 e.printStackTrace();
  11.             }
  12.             System.out.println("Game thread is now resumed......");
  13.         }
  14.         System.out.println("Game thread is stopped......");
  15.     }
  16.     public void stop(){
  17.         isStopped = true;
  18.     }
  19. }
程序输出如下:
Game thread is running......
main is stopping game thread
Game thread is now going to pause
Game thread is now resumed......
Game thread is stopped......
main is finished now
注:
volatile关键字:当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取这个值时,它会去主内存中读取新值。volatile关键字保证了可见性。普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么它就具备了两层语义:
1. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2. 禁止进行指令重排序。
volatile关键字禁止指令重排序有两层意思:
1. 当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行。
2. 在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。
volatile一般情况下不能代替sychronized,因为volatile不能保证操作的原子性,即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++,volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。
三、sleep()方法总结
Thread.sleep()方法可以让线程暂停或停止,它还有一些细节需要注意:
1. Thread.sleep()方法是一个静态方法,它总是可以让当前的线程转入睡眠。
2. 可以调用interrupt()方法把当前睡眠的线程唤醒。
3. sleep()方法不能保证线程能精准地在指定那一毫秒内转入睡眠,它的精度取决于系统的计时器。
4. 它不会释放它所获得的锁。

转载地址:http://jlrxx.baihongyu.com/

你可能感兴趣的文章
linux 禁止文件修改时间,linux 修改文件的时间属性
查看>>
x86 linux 根文件系统6,Linux系列六之根文件系统
查看>>
linux下运行brew,安装 Linuxbrew(示例代码)
查看>>
linux下svn安装教程,linux下安装svn的方法
查看>>
linux 删除不需要的软件,怎么查找并删除不常用的软件包呢?
查看>>
linux图形界面sdk,Linux SDK入门指南
查看>>
linux 修改proc目录,Linux_Linux中系统参数修改命令sysctl的使用讲解,sysctl配置与显示在/proc/sys目录 - phpStudy...
查看>>
linux自启动的无关服务,linux 自启动服务 · Nankle
查看>>
telnet linux root登录,CentOS允许telnet通过root用户进行访问
查看>>
linux下yum安装zabbix,yum安装zabbix4.2
查看>>
Linux下qt注册表,解析 Qt 4.7.0 SDK for Windows 安装后注册表中选项
查看>>
国际学院c语言作业,C语言程序的国际化
查看>>
四阶龙格库塔法c语言程序,四阶龙格库塔法C语言(西安交大)
查看>>
c语言中无windows函数库,关于C语言, GCC/MSVC中,如何写出一个真正意义上的不依赖库的程序?...
查看>>
c语言中break可以用在swift,我可以在Swift中的if语句中使用范围运算符吗?
查看>>
c语言期末考试题库大题及详解答案,C语言期末复习题答案.doc
查看>>
欧洲语言框架A1到C2,法语等级 A1、A2、B1、B2、C1、C2
查看>>
c语言中以追加只写方式打开文本文件,C语言中打开文件读取,写入的操作
查看>>
c语言编程 企业发放,求c语言编程企业员工全年销售额统计及奖金发放系..._统计师_帮考网...
查看>>
C语言编辑中午和英语库,懂英语和C语言的来
查看>>