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()方法所有的线程继续向下运行。
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();
}
}
}