java中Thread合理的中止,退出,暂停方式
最近研究Thread时看到篇好文《Java 理论与实践: 处理 InterruptedException》,摘录下来备用:
http://www.ibm.com/developerworks/cn/java/j-jtp05236.html
1,当一个方法抛出 InterruptedException 时,它不仅告诉您它可以抛出一个特定的检查异常,而且还告诉您其他一些事情。例如,它告诉您它是一个阻塞(blocking)方法,如果您响应得当的话,它将尝试消除阻塞并尽早返回。
2,当一个方法抛出 InterruptedException 时,它是在告诉您,如果执行该方法的线程被中断,它将尝试停止它正在做的事情而提前返回,并通过抛出 InterruptedException 表明它提前返回。 行为良好的阻塞库方法应该能对中断作出响应并抛出 InterruptedException,以便能够用于可取消活动中,而不至于影响响应。
3,如果抛出 InterruptedException 意味着一个方法是阻塞方法,那么调用一个阻塞方法则意味着您的方法也是一个阻塞方法,而且您应该有某种策略来处理 InterruptedException。通常最容易的策略是执行清理,然后自己抛出 InterruptedException,将它传播给调用者。
4,如果捕捉到 InterruptedException 但是不能重新抛出它,那么应该保留中断发生的证据,以便调用栈中更高层的代码能知道中断,并对中断作出响应。该任务可以通过调用当前线程的interrupt() 以 “中断当前线程自己” 来完成。
5,对于执行一个循环中的代码的任务,通常只需为每一个循环迭代检查一次中断。取决于循环执行的时间有多长,任何代码可能要花一些时间才能注意到线程已经被中断(或者是通过调用 Thread.isInterrupted() 方法轮询中断状态,或者是调用一个阻塞方法)。
6,不可中断的阻塞方法:并非所有的阻塞方法都抛出 InterruptedException。输入和输出流类会阻塞等待 I/O 完成,但是它们不抛出 InterruptedException,而且在被中断的情况下也不会提前返回。然而,对于套接字 I/O,如果一个线程关闭套接字,则那个套接字上的阻塞 I/O 操作将提前结束,并抛出一个 SocketException。java.nio 中的非阻塞 I/O 类也不支持可中断 I/O,但是同样可以通过关闭通道或者请求 Selector 上的唤醒来取消阻塞操作。
另据别的文章(忘了出处了):
interrupt方法其实只是改变了中断状态而已,而sleep、wait和join这些方法的内部会不断的检查中断状态的值,从而自己抛出InterruptEdException。
——所以该异常从“设置”到“抛出”不是即时的,但是只要调用过程有上述方法之一,就会最终检测到终端状态并抛出异常。
Thread类中destory,resume,stop,suspend这些废弃方法引用了一篇说明文章:
《Why Are Thread.stop, Thread.suspend,Thread.resume and Runtime.runFinalizersOnExit Deprecated?》
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
以下是根据其写的demo:
1
/**
2 * @author watchzerg
3 */
4 public class ThreadManager implements Runnable{
5 // 线程对象引用
6 private Thread myThread;
7 // 休眠间隔
8 private long interval=1000l;
9 // 用volatile保证变量同步
10 private volatile boolean threadSuspended;
11
12 // 开始
13 public void start(){
14 myThread= new Thread( this,"myThread");
15 myThread.start();
16 }
17
18 /**
19 * 线程体(执行内容):
20 * 如果线程不需要sleep之类的阻塞方法,
21 * 可以通过Thread.isInterrupted()方法来检测中断
22 */
23 @Override
24 public void run() {
25 Thread thisThread=Thread.currentThread();
26 while(myThread==thisThread){
27 try{
28 Thread.sleep(interval);
29 System.out.println(myThread.getName()+" is running.");
30 // 先if一下,避免每次都进入同步块带来的开销
31 if(threadSuspended&&myThread==thisThread){
32 synchronized( this){
33 /* 如果线程在suspend状态被stop,那么myThread==null
34 * 它在下一个循环就快速退出,不再等待了
35 * 不过话说,wait方法本身也会抛中断异常的
36 * 所以我觉得这里去掉"myThread==thisThread"也行
37 * 元方,你怎么看?
38 * */
39 while(threadSuspended&&myThread==thisThread){
40 wait();
41 }
42 }
43 }
44 } catch(InterruptedException e){
45 System.out.println(thisThread.getName()+
46 " is interrupted by InterruptedException.");
47 // 如果这里不打算处理此异常,而又无法抛出去,可以重新断言自己:
48 // Thread.currentThread().interrupt();
49 }
50 }
51 System.out.println(thisThread.getName()+": I'm out, do you copy? ");
52 }
53
54 /**
55 * 停止线程:
56 * 如果是sleep状态,是interrupt起作用;
57 * 如果是运行状态,是myThread==null终止了循环
58 */
59 public synchronized void stop(){
60 if(myThread== null){
61 return;
62 }
63 Thread moribund=myThread;
64 myThread= null;
65 moribund.interrupt();
66 }
67
68 /**
69 * 挂起线程:
70 * 反转条件,并通知其它等待线程
71 */
72 public synchronized void suspend(){
73 threadSuspended=!threadSuspended;
74 if(!threadSuspended){
75 notify();
76 }
77 }
78
79 // test
80 public static void main(String[] args) throws Exception {
81 ThreadManager manager= new ThreadManager();
82 // 开始
83 manager.start();
84 System.out.println("sys:starting ");
85 Thread.sleep(10000l);
86 // 暂停
87 manager.suspend();
88 System.out.println("sys:suspend ");
89 Thread.sleep(10000l);
90 // 恢复
91 manager.suspend();
92 System.out.println("sys:resume ");
93 Thread.sleep(10000l);
94 // 暂停
95 manager.suspend();
96 System.out.println("sys:suspend ");
97 Thread.sleep(5000l);
98 // 在暂停状态下停止
99 manager.stop();
100 System.out.println("sys:stop ");
101 Thread.sleep(10000l);
102 // 退出
103 System.out.println("sys:exit now what?");
104 }
105 }
2 * @author watchzerg
3 */
4 public class ThreadManager implements Runnable{
5 // 线程对象引用
6 private Thread myThread;
7 // 休眠间隔
8 private long interval=1000l;
9 // 用volatile保证变量同步
10 private volatile boolean threadSuspended;
11
12 // 开始
13 public void start(){
14 myThread= new Thread( this,"myThread");
15 myThread.start();
16 }
17
18 /**
19 * 线程体(执行内容):
20 * 如果线程不需要sleep之类的阻塞方法,
21 * 可以通过Thread.isInterrupted()方法来检测中断
22 */
23 @Override
24 public void run() {
25 Thread thisThread=Thread.currentThread();
26 while(myThread==thisThread){
27 try{
28 Thread.sleep(interval);
29 System.out.println(myThread.getName()+" is running.");
30 // 先if一下,避免每次都进入同步块带来的开销
31 if(threadSuspended&&myThread==thisThread){
32 synchronized( this){
33 /* 如果线程在suspend状态被stop,那么myThread==null
34 * 它在下一个循环就快速退出,不再等待了
35 * 不过话说,wait方法本身也会抛中断异常的
36 * 所以我觉得这里去掉"myThread==thisThread"也行
37 * 元方,你怎么看?
38 * */
39 while(threadSuspended&&myThread==thisThread){
40 wait();
41 }
42 }
43 }
44 } catch(InterruptedException e){
45 System.out.println(thisThread.getName()+
46 " is interrupted by InterruptedException.");
47 // 如果这里不打算处理此异常,而又无法抛出去,可以重新断言自己:
48 // Thread.currentThread().interrupt();
49 }
50 }
51 System.out.println(thisThread.getName()+": I'm out, do you copy? ");
52 }
53
54 /**
55 * 停止线程:
56 * 如果是sleep状态,是interrupt起作用;
57 * 如果是运行状态,是myThread==null终止了循环
58 */
59 public synchronized void stop(){
60 if(myThread== null){
61 return;
62 }
63 Thread moribund=myThread;
64 myThread= null;
65 moribund.interrupt();
66 }
67
68 /**
69 * 挂起线程:
70 * 反转条件,并通知其它等待线程
71 */
72 public synchronized void suspend(){
73 threadSuspended=!threadSuspended;
74 if(!threadSuspended){
75 notify();
76 }
77 }
78
79 // test
80 public static void main(String[] args) throws Exception {
81 ThreadManager manager= new ThreadManager();
82 // 开始
83 manager.start();
84 System.out.println("sys:starting ");
85 Thread.sleep(10000l);
86 // 暂停
87 manager.suspend();
88 System.out.println("sys:suspend ");
89 Thread.sleep(10000l);
90 // 恢复
91 manager.suspend();
92 System.out.println("sys:resume ");
93 Thread.sleep(10000l);
94 // 暂停
95 manager.suspend();
96 System.out.println("sys:suspend ");
97 Thread.sleep(5000l);
98 // 在暂停状态下停止
99 manager.stop();
100 System.out.println("sys:stop ");
101 Thread.sleep(10000l);
102 // 退出
103 System.out.println("sys:exit now what?");
104 }
105 }