总结一下个人对线程,线程池的理解(持续更新)
一、线程的3种实现方式
Thread
Runnable
Callable
3种代码实现都很简单,不详聊了(多说一句:callable 可以通过2种方式调用 1 FutureTask 2 线程池时用Future)
总结一下:
Thread的缺陷 new一次就创建一个真实线程
而runnable和callable不一定会创建,可能会线程池里面找到已有的线程去执行所需要的
而runnable和callable的区别在于是否有返回值
二、线程池创建
4种线程池的创建方式
FixedThreadPool 定长线程池(最常用)
CachedThreadPool 可缓存线程池
SingleThreadPool 单个线程池
ScheduledThreadPool 处理周期问题线程池
关于ScheduledThreadPool 线程池,可看我另一篇文章 https://mp.csdn.net/postedit/80309526
三、线程池类型
ExecutorService 和 CompletionService 区别
ExecutorService 非阻塞
CompletionService 阻塞
public class DoubleTypeThreadPool { final static ExecutorService es = Executors.newFixedThreadPool(4); final static CompletionService es1 = new ExecutorCompletionService(es); public static void main(String[] args) { List<Future<Object>> listFuture2 = new ArrayList<Future<Object>>(); // listFuture2.add(es.submit(new BatchThread1())); // listFuture2.add(es.submit(new BatchThread2())); CountDownLatch countDownLatch = new CountDownLatch(2); try { List<Callable<Object>> tasks = new ArrayList<>(); tasks.add(new BatchThread1()); tasks.add(new BatchThread2()); try { listFuture2 = es.invokeAll(tasks); for (Future<Object> o : listFuture2) { try { System.out.println("ExecuteService " + o.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (Exception e) { } finally { countDownLatch.countDown(); } try { countDownLatch.await(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // List<Future<Object>> listFuture = new ArrayList<Future<Object>>(); // // listFuture.add(es1.submit(new BatchThread1())); // listFuture.add(es1.submit(new BatchThread2())); // // // tasks1.add(new BatchThread1()) ; // // tasks1.add(new BatchThread2()) ; // for (Future<Object> o1 : listFuture) { // try { // System.out.println("CompletionService " + o1.get()); // } catch (InterruptedException e) { // e.printStackTrace(); // } catch (ExecutionException e) { // e.printStackTrace(); // } // } } } class BatchThread1<Object> implements Callable<Object> { /** * (非 Javadoc) * * * @return * @throws Exception * @see java.util.concurrent.Callable#call() */ @Override public Object call() throws Exception { Thread.sleep(2000); System.out.println("BatchThread1"); return (Object) Collections.EMPTY_LIST; } } class BatchThread2<Object> implements Callable<Object> { /** * (非 Javadoc) * * * @return * @throws Exception * @see java.util.concurrent.Callable#call() */ @Override public Object call() throws Exception { Thread.sleep(5000); System.out.println("BatchThread2"); return (Object) Collections.EMPTY_LIST; } }
四 、关于线程池关闭
shutdown 使线程池到wait状态 ,清空里面的线程
shutdownNow 使线程池到stop状态,声明周期结束
引用大神的一段话:
执行时间和内存空间是一对永恒的矛盾, 包括线程池在内的很多“池化”思想,都是用内存空间换取执行时间。所以,内存肯定是占用了,但相比当需要线程时去创建,用完后再销毁,所耗费的资源,占用些内存是更合理的。所以才会选择用线程池来维护一些不销毁的线程。
最后,推荐一本好书,《JAVA并发编程实战》 密码 fcbi