线程池嵌套线程池的控制应用(servlet程序控制新线程池)

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

 

import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
import java.util.concurrent.ArrayBlockingQueue;  
import java.util.concurrent.BlockingQueue;  
import java.util.concurrent.RejectedExecutionHandler;  
import java.util.concurrent.ThreadPoolExecutor;  
import java.util.concurrent.TimeUnit;  
  
  
public class Test {     
    
  private PausableThreadPoolExecutor threadPool;     
  
    
  public Test() {     
    threadPool = new      
    PausableThreadPoolExecutor(10, 20, 0, TimeUnit.SECONDS, new ArrayBlockingQueue(8), new ThreadPoolExecutor.DiscardOldestPolicy());     
         
  }    
public static void main(String[] args) throws InterruptedException {  
        Test t = new Test();    
        Object o = new Object();  
        //提交任务给线程池,包括了下句用到的对象锁o。  
            t.threadPool.execute(new newThread(o));  
              
            synchronized(o){   
                o.wait();//等待别的线程唤醒  
            }  
            System.out.printl("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");  
          
      }    
  
}   
 

 

执行的任务(所有的新任务只要继承TestThread和实现Runnable接口,而不用改run()方法,真正实现了与任务无关的异步多线程通信控制。)

class newThread extends TestThread implements Runnable{  
    newThread(Object o) {  
        super(o);  
        // TODO Auto-generated constructor stub  
    }  
  
    public void run() {  
        for (int i = 1; i < 10; i++) {  
            System.out.println(i);  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
    }  
}  
class TestThread {  
    Object o = null;  
  
    TestThread(Object o) {  
        this.o = o;  
    }  
  
    public Object getO() {//用于获取主线程的锁对象   
        return o;  
    }  
  
}  
 

挂钩程序 

class PausableThreadPoolExecutor extends ThreadPoolExecutor {  
      
          
        PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler){  
            super(corePoolSize, maximumPoolSize, keepAliveTime,unit,workQueue,handler) ;  
        }  
        //执行Execute前调用的函数  
        protected void beforeExecute(Thread t,Runnable r){  
            super.beforeExecute(t, r);  
              
        }  
        //执行Execute后调用的函数  
        protected void afterExecute(Runnable r,Throwable t){  
            super.afterExecute(r,t);  
            //System.out.println(r.getClass().getName());  
  
            //运用反射机制和挂钩程序实现线程池的嵌套控制  
            try {  
                Method m = r.getClass().getMethod("getO", null);//得到getO方法  
                Object o = m.invoke(r, null);//执行运行实例的getO方法,得到对象o的锁  
                synchronized(o){   
                    o.notify();//唤醒主程序  
                }  
            } catch (IllegalArgumentException e) {  
                                e.printStackTrace();  
            } catch (SecurityException e) {  
                                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                                e.printStackTrace();  
            } catch (InvocationTargetException e) {  
                                e.printStackTrace();  
            } catch (NoSuchMethodException e) {  
                                e.printStackTrace();  
            }  
          
        }  
          
    }  
 

   最后,关于线程的安全性作一点说明。。大家注意到PausableThreadPoolExecutor类没有成员变量,因为这是由多线程访问的类;主程序也只有线程池一个成员变量,即使主线程是多线程的话,共享这个成员变量也是合理的,因为池就只有一个,除此之外主线程也不该再有其他成员变量;而newThread的超类TestThread类可以拥有成员变量,因为每次提交新任务给线程池的时候都会new一个新的实例,不存在多线程访问的问题。 

打印结果: 

1  
2  
3  
4  
5  
6  
7  
8  
9  
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  
 

分析:先执行了线程池的打印操作1~9,最后唤醒主线程打印<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

 

 

摘自:http://www.iteye.com/topic/567977


版权声明:本文为a38876399原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。