分享

判断多线程是否执行完成(afterexecute)

 hh3755 2011-05-17
思路如下:原文:http://www./view-10791-1.html
本人近来需要在servlet里另起线程池,以便控制,因为servlet的线程是不为我们能控制的,所以无奈之下,使用了ThreadPoolExecutor类。 但是有些任务需要在自己创建的线程池里执行完了,servlet的程序才继续执行。 本来想着用join(),但是线程池的线程引用拿不到,如果在线程池里设置成员变量,又会引起线程不安全(事实上,join()了也没用,因为线程池的线程是不会结束的,join()等待是无结果的)。 苦于成员变量不能设置,局部变量又不可以夸类传递。。 方法一:如果用某个变量控制循环等待,可以实现功能,但不是我要的结果,因为这样的主线程并不是挂起,只是不断循环等待的,一样需要耗费资源,如果线程过多会非常浪费资源。 方法二:在执行任务的程序的run()方法的最后用wait/notify,唤醒主线程,真正实现了异步,主线程并不多耗费资源。缺点是不够灵活,例如:更改了执行的任务,就必须在新任务的run()方法后加入唤醒操作,不能做到与任务无关,所以有了第三种方法。 方法三:用wait/notify和挂钩程序及反射机制的应用,实现了线程池间的通信控制。下面的程序就是介绍第三种方法的。主程序(main函数可模拟是servlet的doPost(),只要保证该类线程安全即可):


另见CSDN的一个文章,这个文章有代码,实现上述第三种思路
答: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()方法所有的线程继续向下运行。

import
java.io.*; import java.util.concurrent.*; import java.util.*; class MyThreadPoolExecutor extends ThreadPoolExecutor{ private boolean hasFinish = false; public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler); // TODO Auto-generated constructor stub } public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); // TODO Auto-generated constructor stub } public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory); // TODO Auto-generated constructor stub } public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); // TODO Auto-generated constructor stub } /* (non-Javadoc) * @see java.util.concurrent.ThreadPoolExecutor#afterExecute(java.lang.Runnable, java.lang.Throwable) */ @Override protected void afterExecute(Runnable r, Throwable t) { // TODO Auto-generated method stub super.afterExecute(r, t); synchronized(this){ System.out.println("自动调用了....afterEx 此时getActiveCount()值:"+this.getActiveCount()); if(this.getActiveCount() == 1)//已执行完任务之后的最后一个线程 { this.hasFinish=true; this.notify(); }//if }// synchronized } public void isEndTask() { synchronized(this){ while (this.hasFinish==false) { System.out.println("等待线程池所有任务结束: wait..."); try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多