- 浏览: 11972 次
- 性别:
- 来自: 苏州
最新评论
在学校的论坛Java版发现很多问关于这样的问题,比如这几个方法有什么区别,想看t.interrupt()方法后线程的中断状态;如何终止一个线程
其实之前已经大部分提及到。现总结一下,然后加上例子,毕竟例子容易理解
http://www.blogjava.net/fhtdy2004/archive/2009/06/08/280728.html中有关interrupt()的解释已经很清楚了
interruptpublic void interrupt()
中断线程。
如果当前线程没有中断它自己(这在任何情况下都是允许的),则该线程的 checkAccess 方法就会被调用,这可能抛出 SecurityException。
如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的
join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int)
方法过程中受阻,则其中断状态将被清除,它还将收到一个 InterruptedException。
如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。
如果该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法一样。
如果以前的条件都没有保存,则该线程的中断状态将被设置。
抛出:
SecurityException - 如果当前线程无法修改该线程
--------------------------------------------------------------------------------
interruptedpublic static boolean interrupted()
测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
返回:
如果当前线程已经中断,则返回 true;否则返回 false。
另请参见:
isInterrupted()
--------------------------------------------------------------------------------
isInterruptedpublic boolean isInterrupted()
测试线程是否已经中断。线程的中断状态 不受该方法的影响。
返回:
如果该线程已经中断,则返回 true;否则返回 false。
另请参见:
interrupted()
t.interrupt()不会中断正在执行的线程,只是将线程的标志位设置成true。但是如果线程在调用
sleep(),join(),wait()方法时线程被中断,则这些方法会抛出InterruptedException,在catch块中捕获到这个
异常时,线程的中断标志位已经被设置成false了,因此在此catch块中调用
t.isInterrupted(),Thread.interrupted()始终都为false,
而t.isInterrupted与Thread.interrupted()的区别是API中已经说明很明显了,Thread.interrupted()假如当前的中断标志为true,则调完后会将中断标志位设置成false
1. package threadtest; 2. 3. import java.util.Timer; 4. import java.util.TimerTask; 5. 6. class CanStop extends Thread { 7. 8. private int counter = 0; 9. 10. public void run() { 11. boolean done = false; 12. try{ 13. Thread.sleep(100);//设置成100比主线程中的500要小 14. }catch(InterruptedException ie){ 15. ie.printStackTrace(); 16. //return;假如要使用interrupt来终止线程则在捕获的InterruptedException中return 17. } 18. while (counter < 100000 &&!done) { 19. System.out.println(counter++); 20. //在主线程中调用stoppable.interrupt()之前为false,假如之后没有调用Thread.interrupted()则一直为true, 21. //否则为第一次为true,调用Thread.interrupted之后为false 22. System.out.println("in thread stoppable.isInterrupted() "+isInterrupted()); 23. 24. //System.out.println("stoppable.isInterrupted() "+Thread.interrupted()); ////在主线程中调用stoppable.interrupt()之前为false,之后只有第一个会显示为true,之后全为false 25. 26. //调用Thread.interrupted()一次会清除线程的中断标志位,因此以后都为false 27. if(Thread.interrupted()==true){ 28. try{ 29. //Thread.interrupted()会清除中断标志位,显然这里面只会调用一次 30. System.out.println("in thread after Thread.interrupted() "+isInterrupted()); 31. sleep(10000); 32. }catch(InterruptedException ie){ 33. ie.printStackTrace(); 34. 35. } 36. } 37. } 38. } 39. 40. } 41. 42. public class CheckInterrupt { 43. public static void main(String[] args) { 44. final CanStop stoppable = new CanStop(); 45. stoppable.start(); 46. new Timer(true).schedule(new TimerTask() { 47. public void run() { 48. System.out.println("Requesting Interrupt"); 49. stoppable.interrupt();//不会中断正在执行的线程,原因是因为interrupt()方法只设置中断状态标志位为true 50. System.out.println("in timer stoppable.isInterrupted() "+stoppable.isInterrupted()); 51. } 52. }, 500); // run() after 500 milliseconds 53. } 54. } 55. 56. 57. 2,关于interrupte()打断sleep() 58. package threadtest; 59. 60. //Understanding join(). 61. 62. class Sleeper extends Thread { 63. private int duration; 64. 65. public Sleeper(String name, int sleepTime) { 66. super(name); 67. duration = sleepTime; 68. start(); 69. } 70. 71. public void run() { 72. try { 73. sleep(duration); 74. } catch (InterruptedException e) { 75. // System.out.println(getName() + " was interrupted. " + 76. // "isInterrupted(): " + isInterrupted()); 77. System.out.println(getName() + " in catch Thread.interrupted(). " 78. + "Thread.interrupted(): " + Thread.interrupted()); 79. return; 80. } 81. System.out.println(getName() + " has awakened"); 82. } 83. } 84. 85. class Joiner extends Thread { 86. private Sleeper sleeper; 87. 88. public Joiner(String name, Sleeper sleeper) { 89. super(name); 90. this.sleeper = sleeper; 91. start(); 92. } 93. 94. public void run() { 95. try { 96. sleeper.join(); 97. } catch (InterruptedException e) { 98. //run方法不能Throw CheckedException,要抛只能抛出RuntimeException,也不会被主线程捕获 99. //要使主线程能够捕获这个RuntimeException请参见另外一篇文章 100. //地址:http://www.blogjava.net/fhtdy2004/archive/2009/08/07/290210.html 101. throw new RuntimeException(e); 102. } 103. System.out.println(getName() + " join completed"); 104. } 105. } 106. 107. public class Joining { 108. 109. public static void main(String[] args) { 110. Sleeper sleepy = new Sleeper("Sleepy", 1500), 111. grumpy = new Sleeper("Grumpy", 1500); 112. Joiner dopey = new Joiner("Dopey", sleepy), 113. doc = new Joiner("Doc",grumpy); 114. grumpy.interrupt(); 115. //doc.interrupt(); 116. 117. } 118. } 119. 120. Sleeper是一个会睡上一段时间的Thread,至于睡多长时间,这要由构造函数的参数决定。Sleeper的run( )的sleep( )可以因时限到期而返回,也可以被interrupt( )打断。catch语句在报告中断的同时,会一并报告isInterrupted( )。当有别的线程调用了本线程的interrupt( )时,会设置一个标记以表示这个这个线程被打断了。当本线程捕获这个异常的时候,会清除这个标志。所以catch语句会永远报告说isInterrupted( )是false。这个标记是用来应付其它情况的,或许在没出异常的情况下,线程要用它来检查自己是不是被中断了。 121. Joiner是另一个线程,它调用了Sleeper的join( ),所以它要等Sleeper醒过来。main( )创建了两个Sleeper分派给两个Joiner。你会发现,不论Sleeper是被打断还是正常结束,Joiner都会随Sleeper一道结束。 122. 123. 124. 125. 126. 127. 2,如何终止一个线程: 128. package test.thread.one; 129. 130. import java.util.Timer; 131. import java.util.TimerTask; 132. 133. class CanStop extends Thread { 134. // Must be volatile: 135. private volatile boolean stop = false; 136. 137. private int counter = 0; 138. 139. public void run() { 140. while (!stop && counter < 100000) { 141. System.out.println(counter++); 142. } 143. if (stop) 144. System.out.println("Detected stop"); 145. } 146. 147. public void requestStop() { 148. stop = true; 149. } 150. } 151. 152. public class Stopping { 153. public static void main(String[] args) { 154. final CanStop stoppable = new CanStop(); 155. stoppable.start(); 156. new Timer(true).schedule(new TimerTask() { 157. public void run() { 158. System.out.println("Requesting stop"); 159. stoppable.requestStop(); 160. } 161. }, 500); // run() after 500 milliseconds 162. } 163. }
stop必须是volatile的,这样才能确保run( )方法能看到它(否则它会使用本地的缓存值)。这个线程的"任务"是打印10,000个数字,所以当counter >= 10000或有人要它停下来的时候,它就结束了。注意requestStop( )不是synchronized,因为stop既是boolean(改成true是一个原子操作)又是volatile的。
1. package test.thread.three; 2. 3. import java.util.Timer; 4. import java.util.TimerTask; 5. 6. class CanStop extends Thread { 7. 8. private boolean stop = false; 9. 10. private int counter = 0; 11. 12. public void run() { 13. boolean done = false; 14. try{ 15. Thread.sleep(100); 16. }catch(InterruptedException ie){ 17. ie.printStackTrace(); 18. //return;假如要使用interrupt来终止线程则在捕获的InterruptedException中return 19. } 20. while (!getStopRequest() && counter < 100000 &&!done) { 21. System.out.println(counter++); 22. } 23. if (getStopRequest()) 24. System.out.println("Detected stop"); 25. } 26. 27. 28. public synchronized boolean getStopRequest(){ 29. return stop; 30. } 31. 32. public synchronized void requestStop() { 33. stop = true; 34. } 35. } 36. 37. public class Stopping { 38. public static void main(String[] args) { 39. final CanStop stoppable = new CanStop(); 40. stoppable.start(); 41. new Timer(true).schedule(new TimerTask() { 42. public void run() { 43. System.out.println("Requesting stop"); 44. stoppable.requestStop(); 45. } 46. }, 500); // run() after 500 milliseconds 47. } 48. } 49. 50. 打断受阻的线程 51. 有时线程受阻之后就不能再做轮询了,比如在等输入,这时你就不能像前面那样去查询旗标了。碰到这种情况,你可以用Thread.interrupt( )方法打断受阻的线程: 52. 53. //: c13:Interrupt.java 54. // Using interrupt() to break out of a blocked thread. 55. import java.util.*; 56. class Blocked extends Thread { 57. public Blocked() { 58. System.out.println("Starting Blocked"); 59. start(); 60. } 61. public void run() { 62. try { 63. synchronized(this) { 64. wait(); // Blocks 65. } 66. } catch(InterruptedException e) { 67. System.out.println("Interrupted"); 68. } 69. System.out.println("Exiting run()"); 70. } 71. } 72. public class Interrupt { 73. static Blocked blocked = new Blocked(); 74. public static void main(String[] args) { 75. new Timer(true).schedule(new TimerTask() { 76. public void run() { 77. System.out.println("Preparing to interrupt"); 78. blocked.interrupt(); 79. blocked = null; // to release it 80. } 81. }, 2000); // run() after 2000 milliseconds 82. } 83. } ///
3.避免过多的同步,永远不要在循环外面调用wait
为了避免死锁的危险,在一个被同步的的方法或者代码快中,永远不要放弃对客户的限制。
换句话说,在一个被同步的区域内部,不要调用一个可被改写的公有或受保护的方法(这样的方法往往是一个抽象方法,但偶尔他们也会有一个默认的实
现,)从包含该同步区域的类的角度来看,这样的方法是一个外来者alien。这个类不知道该类会做什么事情,也控制不力它。客户可以为这个外来方法提供一
个实现,并且在该方法中创建了一个线程,再回调到这个类中。然后,新建的线程试图获取原线程所拥有的那把锁,这样会导致新建的线程被阻塞。如果创建该线程
的方法在等待这个线程完成这个任务,则死锁就形成了。
Object.wait方法的作用是使一个线程等待某个条件。它一定是在一个同步区域中被调用,而且该同步区域锁住了被调用的对象。下面是wait方法的标准模式:
-
1. synchronized(obj){ 2. while(<condition does not hold>) 3. obj.wait(); 4. ...//perform action appropriate to condition 5. }
总是使用wait循环模式来调用wait方法。而不是if来调用。永远不要在循环的外面调用wait。循环被用于等待的前后测试条件
1. package effective.java; 2. 3. import java.io.BufferedInputStream; 4. import java.util.LinkedList; 5. import java.util.List; 6. 7. public abstract class WorkQueue { 8. 9. private final List queue = new LinkedList(); 10. 11. private boolean stopped = false; 12. 13. StringBuffer sb; 14. BufferedInputStream bis; 15. 16. protected WorkQueue(){ 17. new WorkerThread2().start(); 18. } 19. 20. public final void enqueue(Object workItem){ 21. synchronized(queue){ 22. queue.add(workItem); 23. queue.notify(); 24. } 25. } 26. 27. public final void stop(){ 28. synchronized(queue){ 29. stopped = true; 30. queue.notify(); 31. } 32. } 33. 34. protected abstract void processItem(Object workItem)throws InterruptedException; 35. 36. //Broken - invokes alien method from synchronized block 37. private class WorkerThread extends Thread{ 38. public void run(){ 39. while(true){ 40. synchronized(WorkQueue.this.queue){ 41. try{ 42. while(queue.isEmpty() && !stopped){ 43. queue.wait(); 44. } 45. }catch(InterruptedException ie){ 46. ie.printStackTrace(); 47. return; 48. } 49. 50. if(stopped) 51. return; 52. Object workItem = queue.remove(0); 53. try{ 54. processItem(workItem);//lock held 55. }catch(InterruptedException ie){ 56. System.out.println("ddd"+ie); 57. return; 58. } 59. } 60. } 61. } 62. } 63. 64. 65. //Alien method outside synchronized block -"open call" 66. private class WorkerThread2 extends Thread{ 67. public void run(){ 68. while(true){ 69. Object workItem = null; 70. synchronized(WorkQueue.this.queue){ 71. try{ 72. while(queue.isEmpty() && !stopped){ 73. queue.wait(); 74. } 75. }catch(InterruptedException ie){ 76. return; 77. } 78. 79. if(stopped) 80. return; 81. workItem = queue.remove(0); 82. } 83. 84. try{ 85. processItem(workItem);//No lock held 86. }catch(InterruptedException ie){ 87. return; 88. } 89. } 90. } 91. } 92. } 93. 94. package effective.java; 95. 96. public class DisplayQueue extends WorkQueue { 97. 98. @Override 99. protected void processItem(Object workItem) throws InterruptedException { 100. System.out.println(workItem); 101. System.out.println("模拟此线程做耗时工作"); 102. Thread.sleep(1000); 103. } 104. 105. public static void main(String[] args){ 106. WorkQueue wq = new DisplayQueue(); 107. for(int i=0;i<10;i++){ 108. String s = new String("object_"+i); 109. System.out.println("main thread add " + s+" to queue"); 110. wq.enqueue(s); 111. try{ 112. Thread.sleep(500); 113. }catch(InterruptedException ie){ 114. ie.printStackTrace(); 115. } 116. } 117. //wq.stop(); 118. } 119. 120. } 121. 122. 123. 124. class DeadLockQueue extends WorkQueue{ 125. 126. @Override 127. protected void processItem(final Object workItem) throws InterruptedException { 128. 129. Thread child = new Thread(){ 130. public void run(){ 131. //DeadLockQueue.this.enqueue(workItem); 132. System.out.println("在将对象入队列 "+workItem); 133. enqueue(workItem); 134. } 135. }; 136. child.start(); 137. child.join();//dead lock 138. 139. } 140. 141. 142. }
4.保持可运行线程数量尽可能的少的主要技术是,让每个线程做少量的工作,然后使用Object.wait等待某个条件发生,或者使用
Thread.sleep()睡眠一段时间,线程不应该忙-等busy-wait,即反复的检查一个数据结构,以等待某些事件发生。除了使程序易受调度器
的变化的影响外,忙等这种做法还会增加处理器的负担
busy-wait
1. package effective.java; 2. 3. import java.util.LinkedList; 4. import java.util.List; 5. 6. public abstract class WorkQueueBusyWait { 7. 8. private final List queue = new LinkedList(); 9. 10. private boolean stopped = false; 11. 12. protected WorkQueueBusyWait(){ 13. new WorkThread().start(); 14. } 15. 16. public final void enqueue(Object workItem){ 17. synchronized(queue){ 18. queue.add(workItem); 19. } 20. } 21. 22. public final void stop(){ 23. synchronized(queue){ 24. stopped = true; 25. } 26. } 27. 28. protected abstract void processItem(Object workitem) throws InterruptedException; 29. 30. private class WorkThread extends Thread{ 31. public void run(){ 32. final Object QUEUE_IS_EMPTY = new Object(); 33. while(true){ 34. Object workItem = QUEUE_IS_EMPTY; 35. synchronized(queue){ 36. if(stopped) 37. return; 38. if(!queue.isEmpty()) 39. workItem = queue.remove(0); 40. } 41. if(workItem != QUEUE_IS_EMPTY){ 42. try{ 43. processItem(workItem); 44. }catch(InterruptedException ie){ 45. ie.printStackTrace(); 46. return; 47. } 48. } 49. } 50. } 51. } 52. } 53. 54. class PingPongQueue extends WorkQueue{ 55. volatile int count=0; 56. @Override 57. protected void processItem(final Object workItem) throws InterruptedException { 58. count++; 59. WorkQueue recipient = (WorkQueue)workItem; 60. recipient.enqueue(this); 61. } 62. 63. } 64. 65. package effective.java; 66. 67. public class WaitQueuePerf { 68. 69. /** *//** 70. * @param args 71. */ 72. public static void main(String[] args) { 73. 74. PingPongQueue q1 = new PingPongQueue(); 75. PingPongQueue q2 = new PingPongQueue(); 76. q1.enqueue(q2); 77. 78. try{ 79. Thread.sleep(1000); 80. }catch(InterruptedException ie){ 81. ie.printStackTrace(); 82. } 83. 84. int count = q1.count; 85. try{ 86. Thread.sleep(1000); 87. }catch(InterruptedException ie){ 88. ie.printStackTrace(); 89. } 90. System.out.println(q1.count-count); 91. q1.stop(); 92. q2.stop(); 93. 94. } 95. 96. }
发表评论
-
Java程序员的推荐阅读书籍
2011-05-03 11:09 617[/size] 作为Java程序员来说,最痛苦的事情莫过于可以 ... -
文件锁
2011-04-27 15:57 1077文件锁 JDK 1.4引入了文件加锁机制,允许我们同步访问一 ... -
ConcurrentHashMap
2011-04-26 15:18 927ConcurrentHashMap 是 Doug Lea ... -
java ClassLoader
2011-04-25 19:49 806[/size]Java Class Loader 文章分类:J ... -
Oracle语句优化53个规则详解
2011-04-18 15:03 867[/size]Oracle语句优化53个 ... -
JVM参数
2011-04-18 14:41 785[/size]基本回收算法 ... -
javaStax
2011-04-18 14:27 1137[/size]野马(Mustang,Java 6.0代号)相比 ... -
log4J
2011-04-18 13:39 754log4j.rootLogger=INFO, A1 log4j ... -
Java堆栈
2011-04-18 13:25 1626jvm为每个新创建的线程都分配一个堆栈。堆栈以帧为单位保存 ... -
Eclipse 快捷键
2011-04-18 10:00 554Eclipse 快捷键(1) Ctrl+1 快速修复(最经典的 ... -
java.sql.Date,java.sql.Time和java.sql.Timestamp
2011-04-18 09:57 681java.sql.Date,java.sql.Time和jav ... -
Java内存管理
2011-04-18 09:38 524关于Java内存分配,很多 ...
相关推荐
但是编译器或IDE报错说没有处理检查到的InterruptedException。对于InterruptedException,一种常见的处理方式是“生吞” 它,然后什么也不做。本文还介绍了用Java平台提供的协作中断机制来构造灵活的取消策略。各...
在使用Java的过程中,有个情景或许很多人见过,您在编写一个测试程序,程序需要暂停一段时间,于是调用 Thread.sleep()。但是编译器或 IDE 报错说没有处理检查到的 InterruptedException。InterruptedException 是...
j-concurrent 00 IBM developerWorks 中国 : Java 多线程与并发编程专题 ...36 Java 理论与实践 处理 InterruptedException.mht 37 Java 理论与实践 正确使用 Volatile 变量.mht 38 使用泛型和并发改善集合.mht
处理 InterruptedException1
NULL 博文链接:https://pingfang.iteye.com/blog/1124433
自己写一个小程序,我在java1.6.0_10;smslib-v3.4.5下运行成功,主要是以下几个类. Level_Final_Serial.java:串口底层操作 Serial_For_Smslib.java:对Level_Final_Serial的进一步封装,可以直接发送和接受串口信息. ...
自己写一个小程序,我在java1.6.0_10;smslib-v3.4.5下运行成功,...警告: GTW: SMSLINK: Ignoring InterruptedException in Queue.peek(). 如果有能解决的这个异常的,还请多多指教(yangzl0123@163.com或者在我的博客中 ...
语言:java 内容:封装好的redis锁 使用场景: 1.并发情况下 2.对某个字段状态的处理 3.支付回调,重复收到回调数据 使用方法: Object result = redisLockTemplate.execute("REDIS:LOCK:" + id, 1, TimeUnit....
ImageComparerUI——基于Java语言实现的相似图像识别,基于直方图比较算法。 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font...
java源码 package com beancore; import com beancore ui MainFrame; public class Main { public static void main String args[] throws InterruptedException { MainFrame mainFrame; try { mainFrame new...
对空指针异常进行举例,并对实例进行解释,
Java 2实用教程(第三版)实验指导与习题解答 清华大学出版社 (编著 耿祥义 张跃平) 实验模版代码 建议使用文档结构图 (选择Word菜单→视图→文档结构图) 上机实践1 初识Java 4 实验1 一个简单的应用程序 ...
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server ... catch (InterruptedException e) { e.printStackTrace(); } } } }
Java监控u盘插入, // U盘检测 public class CheckU { // 存放磁盘状态 private static Map, Boolean> map = new LinkedHashMap, Boolean>(); // 定义磁盘 private static final String[] arr = new String[] {...
java源码 package com beancore; import com beancore ui MainFrame; public class Main { public static void main String args[] throws InterruptedException { MainFrame mainFrame; try { mainFram e new...
1.C++或Java中的异常处理机制的简单原理和应用。 当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会...
//用java语言编写的一个数字时钟。 import javax.swing.*; import java.awt.*; import java.util.*; import java.text.*; class Clock extends Thread { ClockTest c; Clock(ClockTest c) { this.c = c; } ...
<LI><A title="Java 理论与实践: 关于异常的争论" href="http://www.jspcn.net/htmlnews/11453819700151449.html" target=_blank>Java 理论与实践: 关于异常的争论</A> <LI><A title=Java异常处理的陋习展播 ...
java多线程机制: 例子 1 public class Example1 { static Lefthand left;static Righthand right; public static void main(String args[]) { left=new Lefthand(); //创建两个线程。 right=new Righthand();...
Java Bean 是可复用的组件,对Java Bean并没有严格的规范,理论上讲,任何一个Java类都可以是一个Bean。但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,...