java高并发编程线程池
Posted 有点懒惰的大青年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java高并发编程线程池相关的知识,希望对你有一定的参考价值。
摘自马士兵java并发编程
一、认识Executor、ExecutorService、Callable、Executors
/** * 认识Executor */ package yxxy.c_026; import java.util.concurrent.Executor; public class T01_MyExecutor implements Executor { public static void main(String[] args) { new T01_MyExecutor().execute(new Runnable(){ @Override public void run() { System.out.println("hello executor"); } }); } @Override public void execute(Runnable command) { //new Thread(command).run(); command.run(); } }
Executor执行器是一个接口,只有一个方法execute执行任务,在java的线程池的框架里边,这个是最顶层的接口;
ExecutorService:从Executor接口继承。
Callable:里面call方法,和Runnable接口很像,设计出来都是被其他线程调用的;但是Runnable接口里面run方法是没有返回值的也不能抛出异常;而call方法有返回值可以抛异常;
Executors: 操作Executor的一个工具类;以及操作ExecutorService,ThreadFactory,Callable等;
二、ThreadPool:
/** * 线程池的概念 */ package yxxy.c_026; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class T05_ThreadPool { public static void main(String[] args) throws InterruptedException { ExecutorService service = Executors.newFixedThreadPool(5); //execute submit for (int i = 0; i < 6; i++) { service.execute(() -> { try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); }); } System.out.println(service); service.shutdown(); System.out.println(service.isTerminated()); System.out.println(service.isShutdown()); System.out.println(service); TimeUnit.SECONDS.sleep(5); System.out.println(service.isTerminated()); System.out.println(service.isShutdown()); System.out.println(service); } }
console:
[email protected][Running, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0] false true [email protected][Shutting down, pool size = 5, active threads = 5, queued tasks = 1, completed tasks = 0] pool-1-thread-1 pool-1-thread-3 pool-1-thread-2 pool-1-thread-5 pool-1-thread-4 pool-1-thread-1 true true [email protected][Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 6]
创建了一个线程池,扔了5个线程,接下来要执行6个任务,扔进去线程池里面就启一个线程帮你执行一个,因为这里最多就起5个线程,接下来扔第6个任务的时候,不好意思,它排队了,排在线程池所维护的一个任务队列里面,任务队列大多数使用的都是BlockingQueue,这是线程池的概念;
有什么好处?好处在于如果这个任务执行完了,这个线程不会消失,它执行完任务空闲下来了,如果有新的任务来的时候,直接交给这个线程来运行就行了,不需要新启动线程;从这个概念上讲,如果你的任务和线程池线程数量控制的比较好的情况下,你不需要启动新的线程就能执行很多很多的任务,效率会比较高,并发性好;
service.shutdown():关闭线程池,shutdown是正常的关闭,它会等所有的任务都执行完才会关闭掉;还有一个是shutdownNow,二话不说直接就给关了,不管线程有没有执行完;
service.isTerminated(): 代表的是这里所有执行的任务是不是都执行完了。isShutdown()为true,注意它关了但并不代表它执行完了,只是代表正在关闭的过程之中(注意打印Shutting down)
打印5个线程名字,而且第一个线程执行完了之后,第6个任务来了,第1个线程继续执行,不会有线程6;
当所有线程全部执行完毕之后,线程池的状态为Terminated,表示正常结束,complete tasks=6
线程池里面维护了很多线程,等着你往里扔任务,而扔任务的时候它可以维护着一个任务列表,还没有被执行的任务列表,同样的它还维护着另外一个队列,complete tasks,结束的任务队列,任务执行结束扔到这个队列里,所以,一个线程池维护着两个队列;
三、Future
/** * 认识future */ package yxxy.c_026; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; public class T06_Future { public static void main(String[] args) throws InterruptedException, ExecutionException { /*FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>(){ @Override public Integer call() throws Exception { TimeUnit.MILLISECONDS.sleep(3000); return 1000; } });*/ FutureTask<Integer> task = new FutureTask<>(()->{ TimeUnit.MILLISECONDS.sleep(3000); return 1000; }); new Thread(task).start(); System.out.println(task.get()); //阻塞 //******************************* ExecutorService service = Executors.newFixedThreadPool(5); Future<Integer> f = service.submit(()->{ TimeUnit.MILLISECONDS.sleep(5000); return 1; }); System.out.println(f.isDone()); System.out.println(f.get()); System.out.println(f.isDone()); } }
1000 false 1 true
Future: ExecutorService里面有submit方法,它的返回值是Future类型,因为你扔一个任务进去需要执行一段时间,未来的某一个时间点上,任务执行完了产生给你一个结果,这个Future代表的就是那个Callable的返回值;
---------------
以上是关于java高并发编程线程池的主要内容,如果未能解决你的问题,请参考以下文章