java中如何强制停⽌_Java中终⽌线程的三种⽅法
终⽌线程⼀般建议采⽤的⽅法是让线程⾃⾏结束,进⼊Dead(死亡)状态,就是执⾏完run()⽅法。即如果想要停⽌⼀个线程的执⾏,就要提供某种⽅式让线程能够⾃动结束run()⽅法的执⾏。⽐如设置⼀个标志来控制循环是否执⾏,通过这种⽅式让线程离开run()⽅法。
第⼀种 使⽤Thread类提供的stop()⽅法或suspend()⽅法强制终⽌线程(不安全,不要⽤)
第⼆种 使⽤volatile标记位退出线程
第三种 使⽤ interrupt()⽅法终⽌线程
由于其他原因导致线程停滞(如 I/O),进⼊⾮运⾏状态,停⽌线程的基本思路也是触发⼀个异常,⽽这个异常与导致线程停滞的原因相关。
第⼀种 使⽤Tread类提供的stop()⽅法或suspend()⽅法强制终⽌线程(不安全,不要⽤)
在当前线程中使⽤Thread类提供的stop()⽅法来终⽌其它线程,它会释放已经锁定的所有监视资源。如果当前任何⼀个受到这些监视资源保护的对象处于⼀个不⼀致的状态,其他的线程将会看到这个不⼀致的状态,这可能会导致程序执⾏的不确定性,且这种问题很难被定位。
在当前线程中使⽤Thread类提供的suspend()⽅法来挂起其它线程,然后使⽤resume()⽅法恢复。该⽅法容易引起死锁。线程在调⽤suspend()⽅法时不会释放锁,这就会导致⼀个问题:如果在当前线程中使⽤⼀个suspend()挂起⼀个持有锁的线程,如果当前线程也试图取得同样的对象锁,程序就会发⽣死锁。
鉴于以上两种⽅法的不安全性,Java语⾔已经不建议使⽤以上两种⽅法来终⽌线程。
第⼆种 使⽤volatile标记位退出线程
就是在现线程定义中设置⼀个boolean型的标记位,在线程的run()⽅法中根据这个标记位是true还是false来判断是否退出。这种情况⼀般是将任务放在run()⽅法中的⼀个while循环中执⾏。
st01.stopThread;2
3 class MyThread extendsThread {
4 private volatile boolean exit = false; //volatile保证exit的同步
5
6 public voidexit(){
7 exit = true; //标记位
8 }9
10 @Override11 public voidrun() {12 while (!exit){ //通过标记位控制while循环中的任务
13 System.out.println("This is a thread.");14 }15 }16 }17
18 public classThreadFlag {19 public static void main(String [] args) throwsException{20 MyThread thread1 = newMyThread();21 MyThread thread2 = newMyThread();22 thread1.start(); //启动线程thread1
23 thread2.start(); //启动线程thread2
24 Thread.sleep(1000); //当前线程睡眠5秒钟
it(); //终⽌thread1
it(); //终⽌thread2
27 thread1.join(); //当前线程等待thread1执⾏完
28 thread2.join(); //当前线程等待thread2执⾏完
29 System.out.println(" Thread had been exited");30 }31 }
第三种 使⽤ interrupt ()⽅法终⽌线程
使⽤interrupt()⽅法来终⽌来终⽌线程分为两种情况:
1)线程处于阻塞状态,如使⽤了sleep,同步锁的wait,socket中的receiver,accept等⽅法时,会使线程处于阻塞状态。当调⽤线程的interrupt()⽅法时,会抛出InterruptException异常。阻塞中的那个⽅法抛出这个异常,通过代码捕获该异常,然后break跳出循环状态,从⽽让我们有机会结束这个线程的执⾏。通常很多⼈认为只要调⽤interrupt⽅法线程就会结束,实际上是错的, ⼀定要先捕获InterruptedException异常之后通过break来跳出循环,才能正常结束run⽅法。
2)线程未处于阻塞状态,使⽤isInterrupted()判断线程的中断标志来退出循环。当使⽤interrupt()⽅法时,中断标志就会置true,和使⽤⾃定义的标志来控制循环是⼀样的道理。
为什么要区分进⼊阻塞状态和和⾮阻塞状态两种情况了,是因为当阻塞状态时,如果有interrupt()发⽣,系统除了会抛出InterruptedException异常外,还会调⽤interrupted()函数,调⽤时能获取到中断状态是true的状态,调⽤完之后会复位中断状态为false,所以异常抛出之后通过isInterrupted()是获取不
exited到中断状态是true的状态,从⽽不能退出循环,因此在线程未进⼊阻塞的代码段时是可以通过isInterrupted()来判断中断是否发⽣来控制循环,在进⼊阻塞状态后要通过捕获异常来退出循环。因此使⽤interrupt()来退出线程的最好的⽅式应该是两种情况都要考虑。
阻塞时抛出异常的情景
st01.stopThread;2
3 class MyThread01 extendsThread{
4 @Override
5 public voidrun(){
6 try{
7 sleep(50000); //sleep()是Thread类的静态⽅法
8 System.out.println("线程正在执⾏。");9 } catch (InterruptedException e){ //阻塞时sleep()⽅法会抛出异常
10 System.out.println("线程终⽌。");11 System.out.Message());12 break; //捕获异常之后,退出循环
13 }14 }15 }16
17 public classInterrupt1 {18 public static void main(String [] args)throwsException {19 MyThread01 thread01 = newMyThread01();20 thread01.start();21 System.out.println("在50秒内按任意键终⽌线程");22 ad();23
thread01.interrupt(); //中断线程thread01
24 thread01.join(); //当前线程等待thread01执⾏完
25 System.out.println("线程已经结束");26 }27 }
⾮阻塞不抛出异常的情景
st01.stopThread;2
3 class MyThread01 extendsThread{
4 @Override
5 public voidrun(){
6 while(!isInterrupted()){ // 可以替换成
Thread.interrupted()7 System.out.println("线程执⾏中");8 }9 }10 }11
12 public classInterrupt1 {13 public static void main(String [] args)throwsException {14 MyThread01 thread01 = newMyThread01();15 thread01.start();16 Thread.sleep(10);17 thread01.interrupt(); //中断线程thread01
18 thread01.join(); //当前线程等待thread01执⾏完
19 System.out.println("线程已经结束");20 }21 }
注意:在Thread类中有两个⽅法可以判断线程是否被中断。
⼀个是Thread类的静态⽅法interrupted(),⽤来判断当前线程是否被中断。
⼀个是⾮静态⽅法isInterrupted(),判断调⽤这个⽅法的线程是否被中断,即可以在当前线程中判断其
他线程是否被中断。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论