Loading

Java 中断线程

线程自然终止:自然执行完或抛出未处理异常

Java中有3种方法可以使正在运行的线程终止运行:

1.使用退出标志使线程正常退出;

2.使用stop()方法强行终止线程,但这个方法不推荐使用,因为stop()和suspend(),resume()一样,都是作废的方法,使用它们会发生不可预料的结果;stop()会导致线程不会正确释放资源,suspend()容易导致死锁

3.使用interrupt() 方法中断线程;

 

suspend()死锁例子:

 public class SuspendTest1 {
     private static class SynchronizedObject {
         public synchronized void printString() {
             System.out.println("begin --");
             if (Thread.currentThread().getName().equals("thread-a")) {
                 System.out.println("a线程 suspend..");
                 Thread.currentThread().suspend();
             }
             System.out.println("end ---");
         }
     }
 ​
     public static void main(String[] args) {
         try {
             SynchronizedObject object = new SynchronizedObject();
             Thread thread1 = new Thread() {
                 @Override
                 public void run() {
                     System.out.println(Thread.currentThread().getName());
                     object.printString();
                 }
             };
 ​
             thread1.setName("thread-a");
             thread1.start();
 ​
             TimeUnit.SECONDS.sleep(1);
             Thread thread2 = new Thread() {
                 @Override
                 public void run() {
                     System.out.println("thread2 start...");
                     object.printString();
                     System.out.println("thread2 end...");
                 }
             };
             thread2.setName("thread-b");
             thread2.start();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
 }

  


当thread2运行到thread2 start...后,一致阻塞,用jstack查看,如下:

 "thread-b" #12 prio=5 os_prio=0 tid=0x000000001d169800 nid=0x8658 waiting for monitor entry [0x000000001ddcf000]
    java.lang.Thread.State: BLOCKED (on object monitor)
         at com.example.SuspendTest1$SynchronizedObject.printString(SuspendTest1.java:12)
         - waiting to lock <0x000000076b5a9568> (a com.example.SuspendTest1$SynchronizedObject)
         at com.example.SuspendTest1$2.run(SuspendTest1.java:40)
 ​
    Locked ownable synchronizers:
         - None

  

  线程状态转移图如下:

        


 

发现出现BLOCKED,在thread2调用object.printString()这里出现死锁;

出现这种情况是因为运行到println方法内部时,同步锁不释放;

 public void println(String x) {
     synchronized (this) {
         print(x);
         newLine();
     }
 }

  

 

Java线程是协作式,而非抢占式

抢占式:现行进程在运行过程中,如果有重要或紧迫的进程到达(其状态必须为就绪),则现运行进程将被迫放弃处理器,系统将处理器立刻分配给新到达的进程;如打开任务管理器终止一个进程;

Java协作式:调用一个线程的 interrupt() 方法中断一个线程,并不是强行关闭这个线程,将线程的中断标志位置为true,线程是否中断,由线程本身决定(类似人与人打招呼,但是对方回不回你又是另一回事);如下:

 FutureTask<String> future = new FutureTask<>(new MyCallable());
 Thread thread = new Thread(future);
 thread.start();
 ​
 thread.interrupt();
 ​
 //如果异步任务还没有完成,那么get()会阻塞,直到任务完成后才返回结果
 System.out.println(future.get());

  

这里线程的中断有线程本身决定的;

 

isInterrupted() 判定当前线程是否处于中断状态

static方法interrupted() 判定当前线程是否处于中断状态,同时中断标志位改为false

方法里如果抛出InterruptedException,线程的中断标志位会被复位成false,如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt();

 

posted @ 2020-03-12 13:41  街头卖艺的肖邦  阅读(161)  评论(0编辑  收藏  举报