• 线程的中断(Lock与synchronized)


      Thread包含interrupt()方法,因此你可以终止被阻塞的任务,这个方法将设置线程的中断状态。如果一个线程已经被阻塞,或者试图执行一个阻塞操作。那么设置这个线程的中断状态将

    抛出InterruptedException。当抛出改异常或者该任务调用Thread.interrupted()时,中断状态将被复位。

      查看Thread的API,关于中断的方法有:

      void interrupt()   interrupts this thread

      static boolean interrupted()  Test whether the current thread has been interrupted

      boolean isInterrupted()  Test whether the current thread has been interrupted

      通过几个例子看一下中断的用法和特点:

      例子一,分别模拟了,中断线程sleep,I/O和synchronized修饰的方法。结论:调用interrupt()方法,只有sleep的线程可以被中断,I/O和用synchronized修饰的线程是不能被中断的

    public class Interrupting {
        private static ExecutorService service = Executors.newCachedThreadPool();
    
        static void test(Runnable r) throws InterruptedException{
            Future<?> f = service.submit(r);
            TimeUnit.MILLISECONDS.sleep(100);
            System.out.println("Interrupting: " + r.getClass().getName());
            f.cancel(true); //interrupts if running
            System.out.println("interrupted send to: " + r.getClass().getName());
    
        }
        public static void main(String[] args) throws Exception{
    //        test(new SleepBlocked());
    //        test(new IOBlocked(System.in));
            test(new SynchronizedBlocked());
            TimeUnit.SECONDS.sleep(10);
            System.out.println("Aborting with System.exit(0)");
            System.exit(0);
        }
    }
    
    class SleepBlocked implements Runnable {
        @Override
        public void run() {
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                System.out.println("InterruptedException");
            }
            System.out.println("Exiting SleepBlocked.run()");
        }
    }
    
    class IOBlocked implements Runnable {
        private InputStream is;
    
        public IOBlocked(InputStream is) {
            this.is = is;
        }
    
        @Override
        public void run() {
            try {
                System.out.print("waiting for read:");
                is.read();
            } catch (IOException e) {
                if(Thread.currentThread().isInterrupted()) {
                    System.out.println("Interrupted IO Blocked");
                } else {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("Exiting IOBlocked.run()");
        }
    }
    
    class SynchronizedBlocked implements Runnable {
        public SynchronizedBlocked() {
            new Thread(){
                @Override
                public void run() {
                    f();
                }
            }.start();
        }
    
        public synchronized void f() {
            while(true) { //Never release lock
                Thread.yield();
            }
        }
        @Override
        public void run() {
            System.out.println("try to call f()");
            f();
            System.out.println("Exiting SynchronizedBlocked.run()");
        }
    }

       例子二,sleep是可以被中断的,中断后,中断标识位“复位”

    package org.burning.sport.javase.thread.interrupt;
    
    import java.util.concurrent.TimeUnit;
    
    public class InterruptSleep implements Runnable{
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("开始睡了");
                    TimeUnit.SECONDS.sleep(3);
                }
            } catch (InterruptedException e) {
                boolean isInterrupt = Thread.interrupted();
                //中断状态被复位
                System.out.println("中断状态:" + isInterrupt);
            }
        }
    
        public static void main(String[] args) throws Exception{
            Thread t = new Thread(new InterruptSleep());
            t.start();
            TimeUnit.SECONDS.sleep(5);
            t.interrupt();
            System.out.println("interrupted is: " + t.isInterrupted());
        }
    
    
    }
    /*
    开始睡了
    开始睡了
    interrupted is: false
    中断状态:false
     */

      例子三,普通方法是中断不了的,并且从最后的输出结果 interrupted is: true 看出中断标识位没有被清除。

    package org.burning.sport.javase.thread.interrupt;
    
    import java.util.concurrent.TimeUnit;
    
    public class InterruptCommonTest implements Runnable{
        @Override
        public void run() {
            while (true) {
                System.out.println("你中断一个试试");
                boolean interrupt = Thread.interrupted();
                System.out.println("中断状态" + interrupt);
            }
        }
    
        public static void main(String[] args) throws Exception{
            Thread t = new Thread(new InterruptCommonTest());
            t.setDaemon(true);
            t.start();
            TimeUnit.SECONDS.sleep(5);
            t.interrupt();
            System.out.println("interrupted is: " + t.isInterrupted());
        }
    }
    /*
    中断状态false
    你中断一个试试
    中断状态false
    你中断一个试试
    中断状态false
    interrupted is: true
    你中断一个试试
    中断状态false
     */

       总结:你能够中断对sleep的调用(或者任何要求抛出InterruptedException的调用)。但是你不能中断正在试图获取synchronized锁或者正在试图执行IO操作的线程

       例子四:Lock与中断的关系。

       上面的例子中看到,synchronized是不能被中断的,但是Lock是可以被中断的。这个算是synchronized和Lock的不同点。查看Lock的API,有一个方法

       void lockInterruptibly() throws InrruptedException 就是可以被中断的方式来获取锁的方法。

    package org.burning.sport.javase.thread.interrupt;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class InterruptLockTest implements Runnable{
        private static ReentrantLock lock = new ReentrantLock();
    
        @Override
        public void run() {
            try {
                lock.lockInterruptibly();
                while(true) {
                    Thread.yield();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
    
        public static void main(String[] args) throws Exception{
            InterruptLockTest lockTest = new InterruptLockTest();
            Thread t1 = new Thread(lockTest);
            Thread t2 = new Thread(lockTest);
            t1.start();
            t2.start();
            TimeUnit.SECONDS.sleep(3);
            t2.interrupt();
            System.out.println("结束...");
        }
    }
    /*
    结束...
    java.lang.InterruptedException
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
        at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
        at org.burning.sport.javase.thread.interrupt.InterruptLockTest.run(InterruptLockTest.java:18)
        at java.lang.Thread.run(Thread.java:745)
    Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
        at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
        at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
        at org.burning.sport.javase.thread.interrupt.InterruptLockTest.run(InterruptLockTest.java:25)
        at java.lang.Thread.run(Thread.java:745)
     */

      

    https://gitee.com/play-happy/base-project

    参考:

      【1】《Think in Java》,21.3.4 中断

      【2】《Java 高并发程序设计》,2.2.3 线程中断

  • 相关阅读:
    RPMBUILD源码打包资源汇总(转)
    grep命令:查看配置文件未注释行(转)
    数据结构实验之查找三:树的种类统计(SDUT 3375)
    数据结构实验之查找三:树的种类统计(SDUT 3375)
    数据结构实验之查找四:二分查找(SDUT 3376)
    数据结构实验之查找五:平方之哈希表 (SDUT 3377)
    数据结构实验之查找一:二叉排序树 (SDUT 3373)
    python 正则表达式
    python #!/usr/bin/python 的作用
    欢迎使用CSDN的markdown编辑器
  • 原文地址:https://www.cnblogs.com/happyflyingpig/p/9716055.html
Copyright © 2020-2023  润新知