ThreadPoolExecutor:
1.线程池的线程存储在HashSet中,处理流程:core pool->blocking queue->max pool->reject policy;
2.核心线程池一般不会回收,除非设置了allowCoreThreadTimeOut,线程空闲时处于驻留状态(LockSupport.park);
3.keepAliveTime对于超过核心线程数部分的线程有效,这部分“多余的线程”超过空闲时间会回收。
Runnable vs. Callable:
runnable无返回值,callable包含返回值
submit vs. execute:
submit 包含返回值,可以通过future.get获取返回值或者获取线程异常;
execute无返回值,也无法获取异常
FutureTask:
1.主要属性:任务状态state,执行结果outcome,执行任务callable(任务单元是一个Callable对象,即使通过Runnable对象传入也为通过适配器封装成一个Callable);
2.get方法详解:
代码已经很精炼了,简单做下分析:state为volatile变量,当任务未完成是进入awaitDone方法等待(阻塞调用线程,非任务执行线程),里面是一系列CAS操作和LockSupport.park,在此不做展开了。report方法有必要重点讲下:
可以看到report方法返回正常结果或抛出执行异常,这里有个问题,outcome不是volatile变量,那执行结果的可见性如何保证?这就要看set方法的处理方式了。
3.set方法详解:
首先set方法是在run方法中调用,也就是线程执行完毕的时候设置执行结果。
可以看到outcome=v之后紧跟着UNSAFE.putOrderedInt操作,这行代码的作用有两个:1.state状态设置为正常执行完成;2.在设置state之前插入一个store-store屏障,保证outcome的写入在state写入之前完成。再结合之前的get方法,outcome的读取在state的读取之后(这是由volatile语义保证了,实际是volatile变量读之后的load-load屏障保证执行顺序),因此可以保证获取到最新outcome值。
最后finishCompletion方法通过LockSupport.unpark唤醒被get方法阻塞的线程。