线程池:尽可能地开少线程

Posted ericguoxiaofeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池:尽可能地开少线程相关的知识,希望对你有一定的参考价值。

部分摘自  http://www.cnblogs.com/dolphin0520/p/3932921.html

线程池的5中创建方式

1、Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,
代码: Executors.newSingleThreadExecutor()

2、Cached Thread Pool : 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行,如果线程超过60秒内没执行,那么将被终止并从池中删除,
代码:Executors.newCachedThreadPool()

3、Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,
代码: Executors.newFixedThreadPool(4)
在构造函数中的参数4是线程池的大小,你可以随意设置,也可以和cpu的核数量保持一致,获取cpu的数量int cpuNums = Runtime.getRuntime().availableProcessors();

4、Scheduled Thread Pool : 用来调度即将执行的任务的线程池,
代码:Executors.newScheduledThreadPool()

5、Single Thread Scheduled Pool : 只有一个线程,用来调度执行将来的任务,代码:Executors.newSingleThreadScheduledExecutor()

创建线程池:

/**
 * 列出并发包中的各种线程池
 * @author
 *
 */

public class ExecutorDemo {
    
    public static void main(String[] args) {
        // 创建单线程线程池
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        // 创建可回收的线程池
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        
        int cpuNums = Runtime.getRuntime().availableProcessors();
        System.out.println(cpuNums);
        // 创建固定数量线程池
        ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(cpuNums);
        
        // 创建可调度的线程池
        ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(8);
        // 创建可调度的单线程 线程池    
        ScheduledExecutorService newSingleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
    }
}

 

线程池的两种提交方式:

/**
 * callable 跟runnable的区别:
 * runnable的run方法不会有任何返回结果,所以主线程无法获得任务线程的返回值
 * 
 * callable的call方法可以返回结果,但是主线程在获取时是被阻塞,需要等待任务线程返回才能拿到结果
 * @author
 *
 */

 

execute()方法:
public class ThreadPoolWithRunable {

    
    /**
     * 通过线程池执行线程
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        //创建一个线程池
        ExecutorService pool = Executors.newCachedThreadPool();
        for(int i = 1; i < 50; i++){
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("thread name: " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        
        Thread.sleep(10000);
        
        
        for(int i = 1; i < 50; i++){
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("thread name: " + Thread.currentThread().getName());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        
        
        pool.shutdown();
    }

}

 

submit()方法:(更强大)

public class ThreadPoolWithcallable {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService pool = Executors.newFixedThreadPool(4); 
        
        for(int i = 0; i < 10; i++){
            Future<String> submit = pool.submit(new Callable<String>(){
                @Override
                public String call() throws Exception {
                    //System.out.println("a");
                    System.out.println(Thread.currentThread().getName()+ "-->正在工作");
                    Thread.sleep(5000);
                    System.out.println(Thread.currentThread().getName()+ "-->工作结束");
                    return "b--"+Thread.currentThread().getName();
                }               
               });
            //从Future中get结果,这个方法是会被阻塞的,一直要等到线程任务返回结果
             System.out.println("获取到结果:" + submit.get());  // 小心小心小心(不要乱用)
        } 
            pool.shutdown();

    }

}

 调度线程池:

public class TestPool {

    public static void main(String[] args) throws Exception {
        Future<?> submit = null;
        Random random = new Random();
        
        //创建固定数量线程池
//        ExecutorService exec = Executors.newFixedThreadPool(4);
        
        //创建调度线程池
        ScheduledExecutorService exec = Executors.newScheduledThreadPool(4);
        
        //用来记录各线程的返回结果
        ArrayList<Future<?>> results = new ArrayList<Future<?>>();
        
        for (int i = 0; i < 10; i++) {
            //fixedPool提交线程,runnable无返回值,callable有返回值
            /*submit = exec.submit(new TaskRunnable(i));*/
            /*submit = exec.submit(new TaskCallable(i));*/
            
            //对于schedulerPool来说,调用submit提交任务时,跟普通pool效果一致
            // submit = exec.submit(new TaskCallable(i));
            //对于schedulerPool来说,调用schedule提交任务时,则可按延迟,按间隔时长来调度线程的运行
            submit = exec.schedule(new TaskCallable(i), random.nextInt(10), TimeUnit.SECONDS);
            //存储线程执行结果
            results.add(submit);
            
        }
        
        
        //打印结果
        for(Future f: results){
            boolean done = f.isDone();
            System.out.println(done?"已完成":"未完成");  //从结果的打印顺序可以看到,即使未完成,也会阻塞等待
            System.out.println("线程返回future结果: " + f.get());
        }
        
        exec.shutdown();
        
    }
}

 

代码

public class Test {
    public static void main(String[] args) {   
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5));
        for(int i=0;i<15;i++){
            MyTask myTask = new MyTask(i);
            executor.execute(myTask);
            System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
            executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }
}


class MyTask implements Runnable {
   private int taskNum;
    
   public MyTask(int num) {
       this.taskNum = num;
   }
    
   @Override
   public void run() {
       System.out.println("正在执行task "+taskNum);
       try {
           Thread.currentThread().sleep(4000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("task "+taskNum+"执行完毕");
   }
}

 

END!

1、 Single Thread Executor : 只有一个线程的线程池,因此所有提交的任务是顺序执行,

代码: Executors.newSingleThreadExecutor()

 

2、 Cached Thread Pool : 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行,如果线程超过60秒内没执行,那么将被终止并从池中删除,

代码:Executors.newCachedThreadPool()

 

3、 Fixed Thread Pool : 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待,

代码: Executors.newFixedThreadPool(4)

在构造函数中的参数4是线程池的大小,你可以随意设置,也可以和cpu数量保持一致,获取cpu的数量int cpuNums = Runtime.getRuntime().availableProcessors();

 

4、 Scheduled Thread Pool : 用来调度即将执行的任务的线程池,

代码:Executors.newScheduledThreadPool()

 

5、 Single Thread Scheduled Pool : 只有一个线程,用来调度执行将来的任务,代码:Executors.newSingleThreadScheduledExecutor()

以上是关于线程池:尽可能地开少线程的主要内容,如果未能解决你的问题,请参考以下文章

Java——线程池

线程池与并行度

Java线程池详解

Java线程池详解

Java 线程池详解

Motan在服务provider端用于处理request的线程池