Java 多线程学习-初入线程池

Java 多线程学习-----初入线程池
    使用线程池初衷
    最近项目做代码优化,有一业务功能,大致描述为有20几台分机往总机发送文件,总机在收到文件之后,会往分机反馈数据处理情况。
    这时候想到使用调度来查询总机收到的消息,处理之后分别发送至各分机,为避免排队处理,决定使用多线程,并使用线程池来管理。
    创建线程池
    查找资料之后,采用JDK1.5的java.util.concurrent包创建线程池,本例使用可重用固定线程数的线程池,代码如下:
Java代码 
private static int maxThreads = 20; //最大线程数 
private static ExecutorService e = Executors.newFixedThreadPool(maxThreads);    //创建一个有固定数 量线程的线程池 
    获取任务执行结果
    然后,我使用了FutureTask类来获取任务执行结果,并可以设置任务超时时间,代码如下:
Java代码 
FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true); 
e.execute(ft); 
Boolean fTaskResult = ft.get();  //不设置等待时间,等待计算完成,获取结果 
//Boolean fTaskResult = ft.get(fTimeout, TimeUnit.SECONDS);  //设置等待时间,时间到了之后,获取任务执行结果,如果超时,则会抛出TimeoutException异常 
    如果任务执行超时,我们可以调用FutureTask类的cancel(boolean mayInterruptIfRunning)方法来请求中断任务;
    参数mayInterruptIfRunning - 如果应该中断执行此任务的线程,则为 true;否则允许正在运行的任务运行完成,代码如下:
Java代码 
catch (TimeoutException e) { 
        System.out.println("主线程等待计算结果超时,因此中断任务线程"); 
        ft.cancel(true); 

   但是,这样存在一个问题,就是在调用FutureTask对象的get()方法时,会阻塞线程,直到任务执行完成,会阻止其他线程的执行,网上搜索无果,就用线程池又打开一个线程执行FutureTask对象的get()方法,代码如下:
Java代码 
/**
* 执行任务
* @param t 线程对象
*/ 
public static void beginTask(Thread t){ 
    e.execute(t); 

/**
* 不设置超时时间的任务调用
* @param key   线程标识
* @param t     线程对象
*/ 
public static void beginTask(String key,Thread thread){ 
    final String fKey = key; 
    final FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true); 
    runningTaskMap.put(key, ft);    //存储任务标识 
    e.execute(ft); 
    beginTask(new Thread(){ 
        @Override 
        public void run() { 
            // TODO Auto-generated method stub       
            try {            
                Boolean fTaskResult = ft.get(); 
                if(fTaskResult){ 
                    System.out.println("key为:"+fKey+"的线程执行完成");                      
                } 
            } catch (InterruptedException e) { 
                System.out.println("主线程在等待计算结果时被中断"); 
            } catch (ExecutionException e) { 
                System.out.println("主线程等待计算结果,但计算抛出异常"); 
            }finally{ 
                runningTaskMap.remove(fKey);    //移除线程标识 
            } 
        } 
    }); 

   任务标记
   另外,为了能够获取正在执行的任务,我们对每个任务做了标记,存放在map集合中,代码如下:
Java代码 
//创建一个带有标识的任务集合 
private static Map<String, FutureTask<Boolean>> runningTaskMap = Collections.synchronizedMap(new  HashMap<String, FutureTask<Boolean>>()); 
   当每次调用线程池,就会往map集合中存放记录,调用完之后,再移除掉。
   我们也可以通过标识来中断正在执行的任务,代码如下:
Java代码 
/**
* 根据传入的任务标识,来中断对应任务
* @param key   任务标识
*/ 
public static void intteruptTask(String key){ 
    FutureTask<Boolean> ft = runningTaskMap.get(key); 
    ft.cancel(true); 
    if(ft.isDone()){ 
        runningTaskMap.remove(key); 
    } 

   最后附上完整代码:
Java代码 
package task.concurrent.threadPoor;  
import java.util.Collections; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.FutureTask; 
import java.util.concurrent.TimeUnit; 
import java.util.concurrent.TimeoutException; 
public class FixedThreadPool { 
    private static int maxThreads = 20; //最大线程数 
    private static ExecutorService e = Executors.newFixedThreadPool(maxThreads);    //创建一个有固定数量线程的线程池 
    //创建一个带有标识的任务集合 
    private static Map<String, FutureTask<Boolean>> runningTaskMap = Collections.synchronizedMap(new HashMap<String, FutureTask<Boolean>>()); 
    /**
     * 执行任务
     * @param t 线程对象
     */ 
    public static void beginTask(Thread t){ 
        e.execute(t); 
    } 
     
    /**
     * 不设置超时时间的任务调用
     * @param key   线程标识
     * @param t     线程对象
     */ 
    public static void beginTask(String key,Thread thread){ 
        final String fKey = key; 
        final FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true); 
        runningTaskMap.put(key, ft);    //存储任务标识 
        e.execute(ft);
        beginTask(new Thread(){ 
            @Override 
            public void run() { 
                // TODO Auto-generated method stub       
                try {            
                    Boolean fTaskResult = ft.get(); 
                    if(fTaskResult){ 
                        System.out.println("key为:"+fKey+"的线程执行完成");                      
                    } 
                } catch (InterruptedException e) { 
                    System.out.println("主线程在等待计算结果时被中断"); 
                } catch (ExecutionException e) { 
                 System.out.println("主线程等待计算结果,但计算抛出异常"); 
                }finally{ 
                    runningTaskMap.remove(fKey);    //移除线程标识 
                } 
            } 
        }); 
    } 
     
    /**
     * 设置有超时时间的任务调用
     * @param key       线程标识
     * @param thread    线程对象
     * @param timeout   秒
     */ 
    public static void beginTask(String key, Thread thread, int timeout) { 
        final String fKey = key; 
        final int fTimeout = timeout; 
        final FutureTask<Boolean> ft = new FutureTask<Boolean>(thread,true); 
        runningTaskMap.put(key, ft);    //存储任务标识 
        e.execute(ft); 
         
        beginTask(new Thread(){ 
            @Override 
            public void run() { 
                // TODO Auto-generated method stub       
                try {            
                    Boolean fTaskResult = ft.get(fTimeout, TimeUnit.SECONDS); 
                    if(fTaskResult){ 
                     System.out.println("key为:"+fKey+"的线程执行完");                      
                    } 
                } catch (InterruptedException e) { 
                    System.out.println("主线程在等待计算结果时被中断"); 
                } catch (ExecutionException e) { 
                System.out.println("主线程等待计算结果,但计算抛出异常"); 
                } catch (TimeoutException e) { 
     System.out.println("主线程等待计算结果超时,因此中断任务线程"); 
                    ft.cancel(true); 
                }finally{ 
                    runningTaskMap.remove(fKey);    //移除线程标识 
                } 
            } 
        }); 
    } 
     
    /**
     * 根据传入的任务标识,来中断对应任务
     * @param key   任务标识
     */ 
    public static void intteruptTask(String key){ 
        FutureTask<Boolean> ft = runningTaskMap.get(key); 
        ft.cancel(true); 
        if(ft.isDone()){ 
            runningTaskMap.remove(key); 
        } 
    } 
     
    /**
     * 关闭线程池
     */ 
    public static void shutDownPool(){ 
        e.shutdown(); 
    } 

     广州疯狂软件学院拥有三大课程体系包括:java课程,android课程,ios课程,更多java知识,android知识,ios知识,疯狂软件官网持续更新中。
    疯狂Java培训专注软件开发培训,提升学员就业能力,重点提升实践动手能力。高薪从IT名企请来项目经理为学员亲自授课,对学员进行实战教学,在没有工作经验的学员,在疯狂java,通过大量全真经典企业级项目进行集中培训,学员通过数月培训都可获得1-2年的工作经验,进而在同类的求职者中脱颖而出。疯狂Java培训让你体会java编程的快乐,项目开发的兴奋,成就感,通过短短几个月的时间,让你在半年的时间内掌握8-10万的代码量,掌握Java核心技术,迅速成为技能型的现代化高端人才,迅速获得高薪就业。