天天看點

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,如需轉載請自行聯系原作者

繼續閱讀