ReentrantLock 锁有好几种,除了常用的lock ,tryLock ,其中有个lockInterruptibly 。
1)lock(), 拿不到lock就不罢休,不然线程就一直block。 比较无赖的做法。
2)tryLock(),马上返回,拿到lock就返回true,不然返回false。 比较潇洒的做法。
带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false。比较聪明的做法。
3)lockInterruptibly()就稍微难理解一些。
先说说线程的打扰机制,每个线程都有一个 打扰 标志。这里分两种情况,
1. 线程在sleep或wait,join, 此时如果别的进程调用此进程的 interrupt()方法,此线程会被唤醒并被要求处理InterruptedException;(thread在做IO操作时也可能有类似行为,见java thread api)
2. 此线程在运行中, 则不会收到提醒。但是 此线程的 “打扰标志”会被设置, 可以通过isInterrupted()查看并 作出处理。
lockInterruptibly()和上面的第一种情况是一样的, 线程在请求lock并被阻塞时,如果被interrupt,则“此线程会被唤醒并被要求处理InterruptedException”。并且如果线程已经被interrupt,再使用lockInterruptibly的时候,此线程也会被要求处理interruptedException
测试代码如下,三种方法都有注释,不细说了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * * @author tanlk * @date 2017年7月27日下午5:54:39 */ public class LockTest { //lock()忽视interrupt(), 拿不到锁就 一直阻塞: public static void test1() throws Exception{ final Lock lock = new ReentrantLock(); lock.lock(); TimeUnit.SECONDS.sleep(1); Thread t1 = new Thread( new Runnable() { public void run() { lock.lock(); System.out.println(Thread.currentThread().getName() + "interrupt" ); } }); t1.start(); TimeUnit.SECONDS.sleep(1); t1.interrupt(); TimeUnit.SECONDS.sleep(1); } //tryLock()拿不到锁直接返回 public static void test2() throws Exception{ final Lock lock = new ReentrantLock(); lock.lock(); TimeUnit.SECONDS.sleep(1); Thread t1 = new Thread( new Runnable() { public void run() { lock.tryLock(); System.out.println( "执行完毕" ); } }); t1.start(); TimeUnit.SECONDS.sleep(3); t1.interrupt(); TimeUnit.SECONDS.sleep(1); } //lock.lockInterruptibly()会响应打扰interrupt() 并catch到InterruptedException, //如果屏蔽到t1.interrupt(),lock.lockInterruptibly()也会一直阻塞 public static void test3() throws Exception{ final Lock lock = new ReentrantLock(); lock.lock(); TimeUnit.SECONDS.sleep(1); Thread t1 = new Thread( new Runnable() { public void run() { try { //TimeUnit.SECONDS.sleep(2); lock.lockInterruptibly(); System.out.println( "开始执行" ); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName() + "interrupt" ); e.printStackTrace(); } } }); t1.start(); TimeUnit.SECONDS.sleep(1); t1.interrupt(); TimeUnit.SECONDS.sleep(1); } public static void main(String[] args) throws Exception { test3(); } } |
Eclipse debug test1(),会发现Thread线程一直在Running,不放弃
DestroyJavaVM 在文章 jstack 生成文件中的线程介绍(JVM 内部运行线程)有介绍
LinkedBlockingQueue 的take()和poll()的最大区别就是一个用的lockInterruptibly(),一个用的lock()
版权声明:本文为tlk20071原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。