isEndTask()用while(true){..}來判別全部線程已執行結束,不然程序就不準往下執行.while(true){..}在多線程中是很浪費CPU的,從而使得線程池中各個線程獲得不多的CPU機會去執行本身各自的任務。所以影響了線程池的優點的發揮。
那如何改進代碼呢?
個人建議是:
1)從ThreadPoolExecutor繼承,定製它的回調方法:
protected void afterExecute(Runnable r, Throwable t),在該方法的代碼中,判getActiveCount() 是否是 0,如果0,則置boolean 型變量hasFinished=true;併發出notifyAll()通知,通知synBackup()方法所在的線程,hasFinished已爲true,它能夠開始運行了[主要緣由是:synBackup()方法調用了下邊的waitForEndTask() 方法,而該方法是用wait()等待線程池全部線程運行結束的。]。
2)isEndTask()方法的代碼不能是while(true);改成:若沒有完成,就wait(),放棄CPU,讓CPU寶貴的資源留給線程池中的線程。所以方法名改成waitForEndTask()。代碼以下:
public void waitForEndTask() {
synchronized(變量hasFinished所在的對象){
while (hasFinished==false) {
try{變量hasFinished所在的對象.wait();}
catch(InterruptedException e){}
}
}
3)這樣設計的目的是:當線程池中線程沒有所有運行結束時,synBackup()方法[內部調用了waitForEndTask() ]全部的線程是處於wait()下,不佔用寶貴的CPU資源,讓CPU資源所有留給了線程池中線程。當線程池中全部的線程全運行結束,纔會經過notifyAll()來喚醒synBackup()方法全部的線程繼續向下運行。java
public class MyThreadPoolExecutor extends ThreadPoolExecutor { private boolean hasFinish = false; public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, new CustomThreadFactory(), new CustomRejectedExecutionHandler()); // TODO Auto-generated constructor stub } @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); synchronized (this) { if(this.getActiveCount() == 1){ this.hasFinish = true; this.notify(); } } } public void isEndTask(){ synchronized (this) { while(this.hasFinish == false){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } class CustomThreadFactory implements ThreadFactory{ @Override public Thread newThread(Runnable r) { // TODO Auto-generated method stub Thread t = new Thread(r); System.out.println("------------------------------CustomThreadFactory.............newThread....."); return t; } } class CustomRejectedExecutionHandler implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // TODO Auto-generated method stub try { System.out.println("------------------------------CustomRejectedExecutionHandler.............rejectedExecution....."); executor.getQueue().put(r); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }