2. 并发处理
1. Executors
1.1 Callable & Future
Callable:可以理解为有返回值的Runnable,具体实现返回内容主要靠Future接口的实现处理。
Callable源码Future:Callable返回值监控接口。
Furure源码canncel:取消线程操作
IsCancelled:判断是否取消成功
IsDone:判断是否执行完毕
get:等待任务执行结束,获取返回结果
get(long, TimeUnit): 等待任务执行结束,如果超过指定时间,则中断等待。
1.2 线程中断
线程的interrupt() 和 如何处理InterruptedException进行处理。
不要使用stop() 处理中断,这样有可能存在数据不一致,因为stop会强制释放锁,杀死线程。
在线程内使用Thread.interrupted() 判断中断,并抛出InterruptedException错误。
在捕获错误catch内使用 Thread.currentThread().interrupt() 中断当前线程。
参考博文:https://www.ibm.com/developerworks/cn/java/j-jtp05236.html
1.3 ThreadFactory
线程工厂接口,不用使用new Thread 去新建线程。
Executors内部实现了默认的ThreadFactory 用于创建Thread的
1.4 ThreadPool
线程池的优点: 1. 降低资源浪费,通过重复利用线程减少创建和销毁的消耗;2. 提高响应速度,不用等待创建线程的时间;3. 提供线程的可管理性,防止线程数量不断增加,统一管理。
线程池组成结构:
一个线程池wokers是个Worker set,可用线程都在这个集合里面。
一个任务队列workQueue 是个BlockingQueue,当任务submit到线程池里,先会加入到这个队列里,缓冲队列。
当线程池启动时,会从workQueue内获取Runnable到Worker内执行。
当线程池没有闲置线程时,处理请求会存在队列workQueue中。
线程再次闲置就会去队列获取处理请求。
JDK创建默认线程池:
Executors内初始化线程池的方法1). newFixedThreadPool(吞吐相对于newCachedThreadPool会差一点,长请求、短请求都可以使用)
固定大小的线程池,底层队列使用LinedBlockingQueue队列。
newFixedThreadPool2). newCachedThreadPool(大吞吐处理,短处理请求)
这个线程池根据需要(新任务到来时)创建新的线程,如果有空闲线程则会重复使用,线程空闲了60秒后会被回收。阻塞线程池,没有限制大小,底层队列使用SynchronousQueue,所以这个线程池的吞吐量更大,但是没有闲置大小,有可能会出现线程过多导致内存溢出情况。所以使用这个线程池需要注意控制线程池大小。
newCachedThreadPool3). newScheduledThreadPool(定时处理,延迟处理)
这个线程池方法返回ScheduledThreadPoolExecutor,底层使用队列DelayedQueue达到延迟执行的效果,可以用于定时任务。
newScheduledThreadPool ScheduledExecutorService1.5 Fork, Join
Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。充分利用多核环境。
处理步骤:
1). 拆分小任务,知道拆分到足够小为止;
2). 执行任务,分割的子任务双端队列里,几个线程从队列两端获取任务执行;
3). 合并任务, 执行完的任务结果统一存放在一个队列里,启动一个线程从队列里拿数据并合并这些数据。
主要实现:
ForkJoinPool ----- ExecutorService 的实现
由ForkJoinTask数组和ForkJoinWorkerThread数组组成,ForkJoinTask数组负责存放程序提交给ForkJoinPool的任务,而ForkJoinWorkerThread数组负责执行这些任务。
ForkJoinTask ---- Future 的实现
主要用于分割任务,合并任务,还有任务的处理过程。
ForkJoinWorkerThread 在ForkJoinTask内会用当前线程添加任务,
里面存在一个任务队列
子类:
RecursiveAction:用于没有返回结果的任务。
RecursiveTask :用于有返回结果的任务。
具体原理详情:Fork/Join 原理
1.6 守护线程 & 用户线程
守护线程: 服务于用户线程的线程,但是守护线程会因为没有用户线程而中断。优先级较低。
用户线程: 前台执行线程,主线程执行完用户线程还在。