线程池:尽可能地开少线程
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()
![endif]-->!--[if>![endif]-->!--[if>![endif]-->!--[if>![endif]-->!--[if>以上是关于线程池:尽可能地开少线程的主要内容,如果未能解决你的问题,请参考以下文章