天天看点

Lock应用之 可中断

Thread.interrupt()方法可用于中断指定线程,但线程并不是在任何状态下可被立即中断,一般只有当线程处于阻塞状态(调用wait(),join(),sleep()等方法)时才会被立即中断,如果线程处于不可被立即中断状态,那么Thread.interrupt()只会标志线程的中断状态,以便后续操作用于判断,即isInterrupted()方法会返回true.

线程等待获取内部锁的时候,是一种不可立即中断状态,即线程不会立即响应中断而是会继续等待,这种无义无反顾的等待可能会造成资源浪费或者死锁等问题,后果非常严重。新Lock锁提供了等待锁资源时可立即响应中断的lockInterruptibly()方法和tryLock(long time, TimeUnit unit)方法及其实现,当使用这两个方法去请求锁时,如果主通过Thread.interrupt()对它们发起中断,那么它们会立即响应中断,不再继续等待获取锁,这让主线程(管理调度线程)在特殊情况下可以使用生杀大权,以避免系统陷于死锁状态或者避免资源严重浪费。

tryLock(long time, TimeUnit unit)是加强版的tryLock(),又具有lockInterruptibly()的可被中断特性,既可任其超时主动退出又可中断让其被动退出,很多场合可以使用,但如果想让线程只有当被动中断时才退出,那么就使用lockInterruptibly()方法。

通过测试可以得出以下结论:

内部锁(synchronized) 优先响应锁获取再响应中断

Lock.lock() 优先响应锁获取再响应中断

Lock.tryLock() 判断锁的状态不可用后马上返回不等待

tryLock(long time, TimeUnit unit) 优先响应中断再响应锁获取

Lock.lockInterruptibly() 优先响应中断再响应锁获取

代码示例:

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

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

<code>import</code> <code>java.util.concurrent.TimeUnit;</code>

<code>import</code> <code>java.util.concurrent.locks.Lock;</code>

<code>import</code> <code>java.util.concurrent.locks.ReentrantLock;</code>

<code>public</code> <code>class</code> <code>TestLockInterrupt {</code>

<code>    </code><code>private</code> <code>Lock mLock1;</code>

<code>    </code><code>private</code> <code>Lock mLock2;</code>

<code>    </code><code>private</code> <code>Lock mLock3;</code>

<code>                                                                                                                                                 </code> 

<code>    </code><code>public</code> <code>TestLockInterrupt(){</code>

<code>        </code><code>mLock1 = </code><code>new</code> <code>ReentrantLock();</code>

<code>        </code><code>mLock2 = </code><code>new</code> <code>ReentrantLock();</code>

<code>        </code><code>mLock3 = </code><code>new</code> <code>ReentrantLock();  </code>

<code>    </code><code>}</code>

<code>    </code><code>public</code> <code>void</code> <code>f(){</code>

<code>        </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":try to get lock in f()."</code><code>);</code>

<code>                                                                                                                                                     </code> 

<code>        </code><code>try</code><code>{</code>

<code>            </code><code>synchronized</code><code>(</code><code>this</code><code>){</code>

<code>                </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":get the lock."</code><code>);</code>

<code>                                                                                                                                                             </code> 

<code>                </code><code>if</code><code>(Thread.currentThread().isInterrupted()){</code>

<code>                    </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":already marked as interrupted but still running."</code><code>);</code>

<code>                </code><code>}</code>

<code>                </code><code>TimeUnit.SECONDS.sleep(</code><code>100</code><code>);</code>

<code>            </code><code>}</code>

<code>                                                                                                                                                         </code> 

<code>            </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":release the lock."</code><code>);</code>

<code>        </code><code>}</code>

<code>        </code><code>catch</code><code>(InterruptedException e){</code>

<code>            </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":interrupted."</code><code>);</code>

<code>        </code><code>}          </code>

<code>    </code><code>public</code> <code>void</code> <code>fWithLock(){</code>

<code>        </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":try to get lock in fWithLock()."</code><code>);</code>

<code>        </code><code>mLock1.lock();</code>

<code>            </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":get the lock."</code><code>);</code>

<code>            </code><code>if</code><code>(Thread.currentThread().isInterrupted()){</code>

<code>                </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":already marked as interrupted but still running."</code><code>);</code>

<code>            </code><code>TimeUnit.SECONDS.sleep(</code><code>100</code><code>);</code>

<code>        </code><code>finally</code><code>{</code>

<code>            </code><code>mLock1.unlock();</code>

<code>    </code><code>public</code> <code>void</code> <code>fWithTryLock(){</code>

<code>        </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":try to get lock in fWithTryLock()."</code><code>);</code>

<code>            </code><code>if</code><code>(mLock2.tryLock(</code><code>50</code><code>, TimeUnit.SECONDS)){</code>

<code>                </code><code>try</code><code>{</code>

<code>                    </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":get the lock."</code><code>);</code>

<code>                                                                                                                                                                 </code> 

<code>                    </code><code>if</code><code>(Thread.currentThread().isInterrupted()){</code>

<code>                        </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":already marked as interrupted but still running."</code><code>);</code>

<code>                    </code><code>}</code>

<code>                    </code><code>TimeUnit.SECONDS.sleep(</code><code>100</code><code>);</code>

<code>                </code><code>finally</code><code>{</code>

<code>                    </code><code>mLock2.unlock();</code>

<code>                    </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":release the lock."</code><code>);</code>

<code>            </code><code>}      </code>

<code>        </code><code>}                  </code>

<code>    </code><code>public</code> <code>void</code> <code>fWithLockInterruptibly(){</code>

<code>        </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":try to get lock in fWithLockInterruptibly()."</code><code>);</code>

<code>        </code><code>try</code><code>{       </code>

<code>            </code><code>mLock3.lockInterruptibly();</code>

<code>            </code><code>try</code><code>{</code>

<code>            </code><code>finally</code><code>{</code>

<code>                </code><code>mLock3.unlock();</code>

<code>                </code><code>System.out.println(Thread.currentThread().getName() + </code><code>":release the lock."</code><code>);</code>

<code>    </code><code>private</code> <code>class</code> <code>Worker </code><code>implements</code> <code>Runnable{</code>

<code>        </code><code>private</code> <code>int</code> <code>index;</code>

<code>        </code><code>public</code> <code>Worker(</code><code>int</code> <code>index){</code>

<code>            </code><code>this</code><code>.index = index;</code>

<code>        </code><code>@Override</code>

<code>        </code><code>public</code> <code>void</code> <code>run() {</code>

<code>            </code><code>switch</code><code>(index){</code>

<code>            </code><code>case</code> <code>1</code><code>:</code>

<code>                </code><code>f();</code>

<code>                </code><code>break</code><code>;</code>

<code>            </code><code>case</code> <code>2</code><code>:</code>

<code>                </code><code>fWithLock();</code>

<code>            </code><code>case</code> <code>3</code><code>:</code>

<code>                </code><code>fWithTryLock();</code>

<code>            </code><code>case</code> <code>4</code><code>:</code>

<code>                </code><code>fWithLockInterruptibly();</code>

<code>        </code><code>}  </code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args) {</code>

<code>        </code><code>TestLockInterrupt testLockInterrupt = </code><code>new</code> <code>TestLockInterrupt();</code>

<code>        </code><code>for</code><code>(</code><code>int</code> <code>i=</code><code>1</code><code>; i&lt;=</code><code>4</code><code>; i++){</code>

<code>            </code><code>Thread t1 = </code><code>new</code> <code>Thread(testLockInterrupt.</code><code>new</code> <code>Worker(i));</code>

<code>            </code><code>Thread t2 = </code><code>new</code> <code>Thread(testLockInterrupt.</code><code>new</code> <code>Worker(i));</code>

<code>            </code><code>t1.start();</code>

<code>            </code><code>t2.start();</code>

<code>            </code><code>t1.interrupt();</code>

<code>            </code><code>t2.interrupt();</code>

<code>}</code>

代码输出结果:

<code>Thread-</code><code>0</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>f().</code>

<code>Thread-</code><code>1</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>f().</code>

<code>Thread-</code><code>1</code><code>:</code><code>get</code> <code>the lock.</code>

<code>Thread-</code><code>3</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>fWithLock().</code>

<code>Thread-</code><code>1</code><code>:already marked </code><code>as</code> <code>interrupted but still running.</code>

<code>Thread-</code><code>3</code><code>:</code><code>get</code> <code>the lock.</code>

<code>Thread-</code><code>3</code><code>:already marked </code><code>as</code> <code>interrupted but still running.</code>

<code>Thread-</code><code>7</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>fWithLockInterruptibly().</code>

<code>Thread-</code><code>2</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>fWithLock().</code>

<code>Thread-</code><code>1</code><code>:interrupted.</code>

<code>Thread-</code><code>7</code><code>:interrupted.</code>

<code>Thread-</code><code>3</code><code>:interrupted.</code>

<code>Thread-</code><code>3</code><code>:release the lock.</code>

<code>Thread-</code><code>2</code><code>:</code><code>get</code> <code>the lock.</code>

<code>Thread-</code><code>2</code><code>:already marked </code><code>as</code> <code>interrupted but still running.</code>

<code>Thread-</code><code>2</code><code>:interrupted.</code>

<code>Thread-</code><code>2</code><code>:release the lock.</code>

<code>Thread-</code><code>4</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>fWithTryLock().</code>

<code>Thread-</code><code>4</code><code>:interrupted.</code>

<code>Thread-</code><code>0</code><code>:</code><code>get</code> <code>the lock.</code>

<code>Thread-</code><code>0</code><code>:already marked </code><code>as</code> <code>interrupted but still running.</code>

<code>Thread-</code><code>0</code><code>:interrupted.</code>

<code>Thread-</code><code>5</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>fWithTryLock().</code>

<code>Thread-</code><code>5</code><code>:interrupted.</code>

<code>Thread-</code><code>6</code><code>:</code><code>try</code> <code>to </code><code>get</code> <code>lock </code><code>in</code> <code>fWithLockInterruptibly().</code>

<code>Thread-</code><code>6</code><code>:interrupted.</code>

<code></code>

     本文转自sarchitect 51CTO博客,原文链接:http://blog.51cto.com/stevex/1301184,如需转载请自行联系原作者

继续阅读