总结一下个人对线程,线程池的理解(持续更新)
一、线程的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