interrupt、isinterrupt、interrupted的理解和使用

在java的线程Thread类中有三个方法,比较容易混淆,在这里解释一下
(1)interrupt:置线程的中断状态
(2)isInterrupt:线程是否中断
(3)interrupted:返回线程的上次的中断状态,并清除中断状态

举个例子:

class MyThread extends Thread {  

    ......  

    ......  

    public void run() {  

        try {  

            while(!Thread.currentThread().isInterrupted()) {  

                //当达到队列容量时,在这里会阻塞  

                //put的内部会调用LockSupport.park()这个是用来阻塞线程的方法  

                //当其他线程,调用此线程的interrupt()方法时,会设置一个中断标志  

                //LockSupport.part()中检测到这个中断标志,会抛出InterruptedException,并清除线程的中断标志  

                //因此在异常段调用Thread.currentThread().isInterrupted()返回为false  

                ArrayBlockingQueue.put(somevalue);   

            }  

        } catch (InterruptedException e) {  

            //由于阻塞库函数,如:Object.wait,Thread.sleep除了抛出异常外,还会清除线程中断状态,因此可能在这里要保留线程的中断状态  

            Thread.currentThread().interrupt();  

        }  

    }  

    public void cancel() {  

        interrupt();  

    }  

}  

外部调用  

MyThread thread = new MyThread();  

thread.start();  

......  

thread.cancel();  

thread.isInterrupted();  

 

一般来说,阻塞函数,如:Thread.sleep、Thread.join、Object.wait、LockSupport.park等在检查到线程的中断状态时,会抛出InterruptedException,同时会清除线程的中断状态

对于InterruptedException的处理,可以有两种情况:
(1)外层代码可以处理这个异常,直接抛出这个异常即可
(2)如果不能抛出这个异常,比如在run()方法内,因为在得到这个异常的同时,线程的中断状态已经被清除了,需要保留线程的中断状态,则需要调用Thread.currentThread().interrupt()

另外,Thread.interrupted()在jdk库的源代码中比较常用,因为它既可以得到上一次线程的中断标志值,又可以同时清除线程的中断标志,一举两得,但同时也有坏处,就是这个函数有清除中断状态的副作用,不容易理解.转自:
http://blog.csdn.net/gtuu0123/archive/2010/11/27/6040105.aspx


最近在学习Java线程相关的东西,和大家分享一下,有错误之处欢迎大家指正. 

假如我们有一个任务如下,交给一个Java线程来执行,如何才能保证调用interrupt()来中断它呢? 

Java代码   收藏代码
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.         //死循环执行打印"I am running!" 和做消耗时间的浮点计算  
  7.         while (true) {  
  8.             System.out.println("I am running!");  
  9.               
  10.             for (int i = 0; i < 900000; i++) {  
  11.                 d =  d + (Math.PI + Math.E) / d;  
  12.             }  
  13.             //给线程调度器可以切换到其它进程的信号  
  14.             Thread.yield();  
  15.         }  
  16.     }  
  17. }  
  18.   
  19. public class InterruptTaskTest {  
  20.       
  21.     public static void main(String[] args) throws Exception{  
  22.         //将任务交给一个线程执行  
  23.         Thread t = new Thread(new ATask());  
  24.         t.start();  
  25.           
  26.         //运行一断时间中断线程  
  27.         Thread.sleep(100);  
  28.         System.out.println("****************************");  
  29.         System.out.println("Interrupted Thread!");  
  30.         System.out.println("****************************");  
  31.         t.interrupt();  
  32.     }  
  33. }   


运行这个程序,我们发现调用interrupt()后,程序仍在运行,如果不强制结束,程序将一直运行下去,如下所示: 
Java代码   收藏代码
  1. ......  
  2. I am running!  
  3. I am running!  
  4. I am running!  
  5. I am running!  
  6. ****************************  
  7. Interrupted Thread!  
  8. ****************************  
  9. I am running!  
  10. I am running!  
  11. I am running!  
  12. I am running!  
  13. I am running!  
  14. ....  

虽然中断发生了,但线程仍然在进行,离开线程有两种常用的方法: 
抛出InterruptedException和用Thread.interrupted()检查是否发生中断,下面分别看一下这两种方法: 
1.在阻塞操作时如Thread.sleep()时被中断会抛出InterruptedException(注意,进行不能中断的IO操作而阻塞和要获得对象的锁调用对象的synchronized方法而阻塞时不会抛出InterruptedException) 
Java代码   收藏代码
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.         //死循环执行打印"I am running!" 和做消耗时间的浮点计算  
  7.         try {  
  8.             while (true) {  
  9.                 System.out.println("I am running!");  
  10.                   
  11.                 for (int i = 0; i < 900000; i++) {  
  12.                     d =  d + (Math.PI + Math.E) / d;  
  13.                 }  
  14.                 //休眠一断时间,中断时会抛出InterruptedException  
  15.                 Thread.sleep(50);  
  16.             }  
  17.         } catch (InterruptedException e) {  
  18.             System.out.println("ATask.run() interrupted!");  
  19.         }  
  20.     }  
  21. }  

程序运行结果如下: 
Java代码   收藏代码
  1. I am running!  
  2. I am running!  
  3. ****************************  
  4. Interrupted Thread!  
  5. ****************************  
  6. ATask.run() interrupted!  

可以看到中断任务时让任务抛出InterruptedException来离开任务. 

2.Thread.interrupted()检查是否发生中断.Thread.interrupted()能告诉你线程是否发生中断,并将清除中断状态标记,所以程序不会两次通知你线程发生了中断. 
Java代码   收藏代码
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.           
  7.         //检查程序是否发生中断  
  8.         while (!Thread.interrupted()) {  
  9.             System.out.println("I am running!");  
  10.   
  11.             for (int i = 0; i < 900000; i++) {  
  12.                 d = d + (Math.PI + Math.E) / d;  
  13.             }  
  14.         }  
  15.   
  16.         System.out.println("ATask.run() interrupted!");  
  17.     }  
  18. }  

程序运行结果如下: 
Java代码   收藏代码
  1. I am running!  
  2. I am running!  
  3. I am running!  
  4. I am running!  
  5. I am running!  
  6. I am running!  
  7. I am running!  
  8. ****************************  
  9. Interrupted Thread!  
  10. ****************************  
  11. ATask.run() interrupted!  


我们可结合使用两种方法来达到可以通过interrupt()中断线程.请看下面例子: 
Java代码   收藏代码
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.           
  7.         try {  
  8.         //检查程序是否发生中断  
  9.         while (!Thread.interrupted()) {  
  10.             System.out.println("I am running!");  
  11.             //point1 before sleep  
  12.             Thread.sleep(20);  
  13.             //point2 after sleep  
  14.             System.out.println("Calculating");  
  15.             for (int i = 0; i < 900000; i++) {  
  16.                 d = d + (Math.PI + Math.E) / d;  
  17.             }  
  18.         }  
  19.           
  20.         } catch (InterruptedException e) {  
  21.             System.out.println("Exiting by Exception");  
  22.         }  
  23.           
  24.         System.out.println("ATask.run() interrupted!");  
  25.     }  
  26. }  

在point1之前处point2之后发生中断会产生两种不同的结果,可以通过修改InterruptTaskTest main()里的Thread.sleep()的时间来达到在point1之前产生中断或在point2之后产生中断. 
如果在point1之前发生中断,程序会在调用Thread.sleep()时抛出InterruptedException从而结束线程.这和在Thread.sleep()时被中断是一样的效果.程序运行结果可能如下: 
Java代码   收藏代码
  1. I am running!  
  2. Calculating  
  3. I am running!  
  4. Calculating  
  5. I am running!  
  6. Calculating  
  7. I am running!  
  8. ****************************  
  9. Interrupted Thread!  
  10. ****************************  
  11. Exiting by Exception  
  12. ATask.run() interrupted!  

如果在point2之后发生中断,线程会继续执行到下一次while判断中断状态时.程序运行结果可能如下: 
Java代码   收藏代码
  1. I am running!  
  2. Calculating  
  3. I am running!  
  4. Calculating  
  5. I am running!  
  6. Calculating  
  7. ****************************  
  8. Interrupted Thread!  
  9. ****************************  
  10. ATask.run() interrupted!  



在学校的论坛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 
Java代码   收藏代码
  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的。 

或者 
Java代码   收藏代码
  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方法的标准模式: 
Java代码   收藏代码
  1. synchronized(obj){  
  2.       while(<condition does not hold>)  
  3.             obj.wait();  
  4.       ...//perform action appropriate to condition  
  5. }  
总是使用wait循环模式来调用wait方法。而不是if来调用。永远不要在循环的外面调用wait。循环被用于等待的前后测试条件 

Java代码   收藏代码
  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 
Java代码   收藏代码
  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. }  

interrupt和isInterrupted是Java线程中用于中断线程的方法和判断线程是否被中断的方法。 interrupt方法是Thread类的一个方法,用于请求中断当前线程。当调用interrupt方法时,如果当前线程正在被阻塞(例如通过sleep或wait方法),会抛出InterruptedException异常,并且中断标志位会被置为true。如果当前线程没有被阻塞,中断标志位仅仅被置为true,不会有任何其他影响。 isInterrupted方法是Thread类的另一个方法,用于判断当前线程是否被中断。该方法仅是对中断标志位的一个判断,并不会改变中断标志位的状态。如果中断标志位为true,则返回true;否则返回false。 在实例中,可以看到一个使用interrupt方法的例子。当调用thread.interrupt()方法时,线程会被中断,如果线程正在阻塞,会抛出InterruptedException异常,可以通过捕获该异常来处理中断信号。 另外,在使用interrupt方法时,需要注意到,当try-catch捕获到InterruptedException异常时,中断信号会被抹除,所以如果执行在catch异常前,isInterrupted方法将返回true,可以正常退出。否则,中断信号被抹除后,isInterrupted方法得到的值为false,循环会继续执行。 总之,interrupt方法用于请求中断当前线程,isInterrupted方法用于判断线程是否被中断。在处理中断时,需要注意捕获InterruptedException异常并处理中断信号。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值