在學(xué)校的論壇Java版發(fā)現(xiàn)很多問(wèn)關(guān)于這樣的問(wèn)題,,比如這幾個(gè)方法有什么區(qū)別,想看t.interrupt()方法后線程的中斷狀態(tài),;如何終止一個(gè)線程 其實(shí)之前已經(jīng)大部分提及到?,F(xiàn)總結(jié)一下,然后加上例子,畢竟例子容易理解 http://www./fhtdy2004/archive/2009/06/08/280728.html中有關(guān)interrupt()的解釋已經(jīng)很清楚了 interruptpublic void interrupt()
interruptedpublic static boolean interrupted()
isInterruptedpublic boolean isInterrupted()
t.interrupt()不會(huì)中斷正在執(zhí)行的線程,,只是將線程的標(biāo)志位設(shè)置成true,。但是如果線程在調(diào)用sleep(),join(),wait()方法時(shí)線程被中斷,則這些方法會(huì)拋出InterruptedException,,在catch塊中捕獲到這個(gè)異常時(shí),,線程的中斷標(biāo)志位已經(jīng)被設(shè)置成false了,因此在此catch塊中調(diào)用t.isInterrupted(),Thread.interrupted()始終都為false, 而t.isInterrupted與Thread.interrupted()的區(qū)別是API中已經(jīng)說(shuō)明很明顯了,Thread.interrupted()假如當(dāng)前的中斷標(biāo)志為true,,則調(diào)完后會(huì)將中斷標(biāo)志位設(shè)置成false package threadtest;
import java.util.Timer; import java.util.TimerTask; class CanStop extends Thread { private int counter = 0; public void run() { boolean done = false; try{ Thread.sleep(100);//設(shè)置成100比主線程中的500要小 }catch(InterruptedException ie){ ie.printStackTrace(); //return;假如要使用interrupt來(lái)終止線程則在捕獲的InterruptedException中return } while (counter < 100000 &&!done) { System.out.println(counter++); //在主線程中調(diào)用stoppable.interrupt()之前為false,假如之后沒(méi)有調(diào)用Thread.interrupted()則一直為true, //否則為第一次為true,調(diào)用Thread.interrupted之后為false System.out.println("in thread stoppable.isInterrupted() "+isInterrupted()); //System.out.println("stoppable.isInterrupted() "+Thread.interrupted());////在主線程中調(diào)用stoppable.interrupt()之前為false,之后只有第一個(gè)會(huì)顯示為true,之后全為false //調(diào)用Thread.interrupted()一次會(huì)清除線程的中斷標(biāo)志位,因此以后都為false if(Thread.interrupted()==true){ try{ //Thread.interrupted()會(huì)清除中斷標(biāo)志位,顯然這里面只會(huì)調(diào)用一次 System.out.println("in thread after Thread.interrupted() "+isInterrupted()); sleep(10000); }catch(InterruptedException ie){ ie.printStackTrace(); } } } } } public class CheckInterrupt { public static void main(String[] args) { final CanStop stoppable = new CanStop(); stoppable.start(); new Timer(true).schedule(new TimerTask() { public void run() { System.out.println("Requesting Interrupt"); stoppable.interrupt();//不會(huì)中斷正在執(zhí)行的線程,原因是因?yàn)閕nterrupt()方法只設(shè)置中斷狀態(tài)標(biāo)志位為true System.out.println("in timer stoppable.isInterrupted() "+stoppable.isInterrupted()); } }, 500); // run() after 500 milliseconds } } 2,關(guān)于interrupte()打斷sleep() package threadtest;
//Understanding join(). class Sleeper extends Thread { private int duration; public Sleeper(String name, int sleepTime) { super(name); duration = sleepTime; start(); } public void run() { try { sleep(duration); } catch (InterruptedException e) { // System.out.println(getName() + " was interrupted. " + // "isInterrupted(): " + isInterrupted()); System.out.println(getName() + " in catch Thread.interrupted(). " + "Thread.interrupted(): " + Thread.interrupted()); return; } System.out.println(getName() + " has awakened"); } } class Joiner extends Thread { private Sleeper sleeper; public Joiner(String name, Sleeper sleeper) { super(name); this.sleeper = sleeper; start(); } public void run() { try { sleeper.join(); } catch (InterruptedException e) { //run方法不能Throw CheckedException,要拋只能拋出RuntimeException,也不會(huì)被主線程捕獲 //要使主線程能夠捕獲這個(gè)RuntimeException請(qǐng)參見(jiàn)另外一篇文章 //地址:http://www./fhtdy2004/archive/2009/08/07/290210.html throw new RuntimeException(e); } System.out.println(getName() + " join completed"); } } public class Joining { public static void main(String[] args) { Sleeper sleepy = new Sleeper("Sleepy", 1500), grumpy = new Sleeper("Grumpy", 1500); Joiner dopey = new Joiner("Dopey", sleepy), doc = new Joiner("Doc",grumpy); grumpy.interrupt(); //doc.interrupt(); } } Sleeper是一個(gè)會(huì)睡上一段時(shí)間的Thread,至于睡多長(zhǎng)時(shí)間,,這要由構(gòu)造函數(shù)的參數(shù)決定,。Sleeper的run( )的sleep( )可以因時(shí)限到期而返回,也可以被interrupt( )打斷,。catch語(yǔ)句在報(bào)告中斷的同時(shí),,會(huì)一并報(bào)告isInterrupted( )。當(dāng)有別的線程調(diào)用了本線程的interrupt( )時(shí),,會(huì)設(shè)置一個(gè)標(biāo)記以表示這個(gè)這個(gè)線程被打斷了,。當(dāng)本線程捕獲這個(gè)異常的時(shí)候,會(huì)清除這個(gè)標(biāo)志,。所以catch語(yǔ)句會(huì)永遠(yuǎn)報(bào)告說(shuō)isInterrupted( )是false,。這個(gè)標(biāo)記是用來(lái)應(yīng)付其它情況的,或許在沒(méi)出異常的情況下,,線程要用它來(lái)檢查自己是不是被中斷了,。 2,,如何終止一個(gè)線程: package test.thread.one;
stop必須是volatile的,,這樣才能確保run( )方法能看到它(否則它會(huì)使用本地的緩存值)。這個(gè)線程的"任務(wù)"是打印10,000個(gè)數(shù)字,,所以當(dāng)counter >= 10000或有人要它停下來(lái)的時(shí)候,,它就結(jié)束了。注意requestStop( )不是synchronized,,因?yàn)閟top既是boolean(改成true是一個(gè)原子操作)又是volatile的,。import java.util.Timer; import java.util.TimerTask; class CanStop extends Thread { // Must be volatile: private volatile boolean stop = false; private int counter = 0; public void run() { while (!stop && counter < 100000) { System.out.println(counter++); } if (stop) System.out.println("Detected stop"); } public void requestStop() { stop = true; } } public class Stopping { public static void main(String[] args) { final CanStop stoppable = new CanStop(); stoppable.start(); new Timer(true).schedule(new TimerTask() { public void run() { System.out.println("Requesting stop"); stoppable.requestStop(); } }, 500); // run() after 500 milliseconds } } 或者 package test.thread.three;
import java.util.Timer; import java.util.TimerTask; class CanStop extends Thread { private boolean stop = false; private int counter = 0; public void run() { boolean done = false; try{ Thread.sleep(100); }catch(InterruptedException ie){ ie.printStackTrace(); //return;假如要使用interrupt來(lái)終止線程則在捕獲的InterruptedException中return } while (!getStopRequest() && counter < 100000 &&!done) { System.out.println(counter++); } if (getStopRequest()) System.out.println("Detected stop"); } public synchronized boolean getStopRequest(){ return stop; } public synchronized void requestStop() { stop = true; } } public class Stopping { public static void main(String[] args) { final CanStop stoppable = new CanStop(); stoppable.start(); new Timer(true).schedule(new TimerTask() { public void run() { System.out.println("Requesting stop"); stoppable.requestStop(); } }, 500); // run() after 500 milliseconds } } 打斷受阻的線程
有時(shí)線程受阻之后就不能再做輪詢了,比如在等輸入,,這時(shí)你就不能像前面那樣去查詢旗標(biāo)了,。碰到這種情況,,你可以用Thread.interrupt( )方法打斷受阻的線程: //: c13:Interrupt.java // Using interrupt() to break out of a blocked thread. import java.util.*; class Blocked extends Thread { public Blocked() { System.out.println("Starting Blocked"); start(); } public void run() { try { synchronized(this) { wait(); // Blocks } } catch(InterruptedException e) { System.out.println("Interrupted"); } System.out.println("Exiting run()"); } } public class Interrupt { static Blocked blocked = new Blocked(); public static void main(String[] args) { new Timer(true).schedule(new TimerTask() { public void run() { System.out.println("Preparing to interrupt"); blocked.interrupt(); blocked = null; // to release it } }, 2000); // run() after 2000 milliseconds } } /// 3.避免過(guò)多的同步,永遠(yuǎn)不要在循環(huán)外面調(diào)用wait 為了避免死鎖的危險(xiǎn),,在一個(gè)被同步的的方法或者代碼快中,,永遠(yuǎn)不要放棄對(duì)客戶的限制。
package effective.java;
import java.io.BufferedInputStream; import java.util.LinkedList; import java.util.List; public abstract class WorkQueue { private final List queue = new LinkedList(); private boolean stopped = false; StringBuffer sb; BufferedInputStream bis; protected WorkQueue(){ new WorkerThread2().start(); } public final void enqueue(Object workItem){ synchronized(queue){ queue.add(workItem); queue.notify(); } } public final void stop(){ synchronized(queue){ stopped = true; queue.notify(); } } protected abstract void processItem(Object workItem)throws InterruptedException; //Broken - invokes alien method from synchronized block private class WorkerThread extends Thread{ public void run(){ while(true){ synchronized(WorkQueue.this.queue){ try{ while(queue.isEmpty() && !stopped){ queue.wait(); } }catch(InterruptedException ie){ ie.printStackTrace(); return; } if(stopped) return; Object workItem = queue.remove(0); try{ processItem(workItem);//lock held }catch(InterruptedException ie){ System.out.println("ddd"+ie); return; } } } } } //Alien method outside synchronized block -"open call" private class WorkerThread2 extends Thread{ public void run(){ while(true){ Object workItem = null; synchronized(WorkQueue.this.queue){ try{ while(queue.isEmpty() && !stopped){ queue.wait(); } }catch(InterruptedException ie){ return; } if(stopped) return; workItem = queue.remove(0); } try{ processItem(workItem);//No lock held }catch(InterruptedException ie){ return; } } } } } package effective.java;
public class DisplayQueue extends WorkQueue { @Override protected void processItem(Object workItem) throws InterruptedException { System.out.println(workItem); System.out.println("模擬此線程做耗時(shí)工作"); Thread.sleep(1000); } public static void main(String[] args){ WorkQueue wq = new DisplayQueue(); for(int i=0;i<10;i++){ String s = new String("object_"+i); System.out.println("main thread add " + s+" to queue"); wq.enqueue(s); try{ Thread.sleep(500); }catch(InterruptedException ie){ ie.printStackTrace(); } } //wq.stop(); } } class DeadLockQueue extends WorkQueue{ @Override protected void processItem(final Object workItem) throws InterruptedException { Thread child = new Thread(){ public void run(){ //DeadLockQueue.this.enqueue(workItem); System.out.println("在將對(duì)象入隊(duì)列 "+workItem); enqueue(workItem); } }; child.start(); child.join();//dead lock } } 4.保持可運(yùn)行線程數(shù)量盡可能的少的主要技術(shù)是,讓每個(gè)線程做少量的工作,,然后使用Object.wait等待某個(gè)條件發(fā)生,,或者使用Thread.sleep()睡眠一段時(shí)間,線程不應(yīng)該忙-等busy-wait,,即反復(fù)的檢查一個(gè)數(shù)據(jù)結(jié)構(gòu),,以等待某些事件發(fā)生。除了使程序易受調(diào)度器的變化的影響外,,忙等這種做法還會(huì)增加處理器的負(fù)擔(dān) busy-wait package effective.java;
import java.util.LinkedList; import java.util.List; public abstract class WorkQueueBusyWait { private final List queue = new LinkedList(); private boolean stopped = false; protected WorkQueueBusyWait(){ new WorkThread().start(); } public final void enqueue(Object workItem){ synchronized(queue){ queue.add(workItem); } } public final void stop(){ synchronized(queue){ stopped = true; } } protected abstract void processItem(Object workitem) throws InterruptedException; private class WorkThread extends Thread{ public void run(){ final Object QUEUE_IS_EMPTY = new Object(); while(true){ Object workItem = QUEUE_IS_EMPTY; synchronized(queue){ if(stopped) return; if(!queue.isEmpty()) workItem = queue.remove(0); } if(workItem != QUEUE_IS_EMPTY){ try{ processItem(workItem); }catch(InterruptedException ie){ ie.printStackTrace(); return; } } } } } } class PingPongQueue extends WorkQueue{ volatile int count=0; @Override protected void processItem(final Object workItem) throws InterruptedException { count++; WorkQueue recipient = (WorkQueue)workItem; recipient.enqueue(this); } } package effective.java;
public class WaitQueuePerf { /** * @param args */ public static void main(String[] args) { PingPongQueue q1 = new PingPongQueue(); PingPongQueue q2 = new PingPongQueue(); q1.enqueue(q2); try{ Thread.sleep(1000); }catch(InterruptedException ie){ ie.printStackTrace(); } int count = q1.count; try{ Thread.sleep(1000); }catch(InterruptedException ie){ ie.printStackTrace(); } System.out.println(q1.count-count); q1.stop(); q2.stop(); } } |
|