zoukankan      html  css  js  c++  java
  • 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();

     

  • 相关阅读:
    VUE中tinymce设置字体大小、字体选择(就没有一篇文章能说的清楚的,那么我就说清楚这个问题)
    解决每次git push时需要输入用户名密码的问题
    vue路由,解决同一路由页面多次触发不刷新页面【vue开发】
    函数防抖和节流
    h5页面如何判断是系统Android,ios还是微信等
    react 结合 Promise 和 async await 解决多个异步请求 后统一设置状态问题
    对数组对象递归遍历给子对象添加父对象属性的方法
    React Hooks 使用指南
    webpack配置介绍
    React 实现键盘监听事件
  • 原文地址:https://www.cnblogs.com/coder-zyc/p/12468729.html
Copyright © 2011-2022 走看看