- CopyOnWriteArrayList
思想是读写分离,添加元素的时候,不直接往容器中添加,而是先把容器复制一份,往复制的容器中添加一个数据之后,在把原有的容器指向拷贝后的数据。在读取数据的时候读取到的是原有数据,没有加锁,利用一种读写分离的思想
。为什么会出现异常,因为List 添加的时候需要有一个游标来回指向,并发的时候游标就会出错。 - FutureTask+Callable 实现第三种多线程方式。
- BlockingQueue 阻塞队列方法 . 阻塞添加 put , 阻塞获取 take 。 超时添加 offer 超时获取 poll
- 线程池 ExecutorService 接口 ThreadPoolExecutor 实现类
public ThreadPoolExecutor(int corePoolSize, // 1
int maximumPoolSize, // 2
long keepAliveTime, // 3
TimeUnit unit, // 4
BlockingQueue<Runnable> workQueue, // 5
ThreadFactory threadFactory, // 6
RejectedExecutionHandler handler ) { //7
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
corePoolSize 核心线程数
maximumPoolSize 最大线程数
keepAliveTime 存活时间
TimeUnit unit 存活时间单位
BlockingQueue workQueue 阻塞队列
ThreadFactory threadFactory 线程工厂
RejectedExecutionHandler handler 拒绝策略
线程池工作流程
1.1 来了一个线程之后先判断当前线程数有没有大于核心线程数
,小于直接创建,大于则放入阻塞队列
1.2 阻塞队列如果满了的话就会判断 最大线程数满了没有
没满就创建
1.3 最大线程数如果也满了,则会调用拒绝策略
拒绝策略
1.4 AbortPolicy 默认拒绝策略. 直接抛异常
1.5 CallerRunsPolicy . 让调用线程池方法的线程自己去处理这个事情
1.6 DiscardPolicy 丢弃任务
5. ForkJoinPool
-> ForkJoinTask
-> RecursiveTask
class ForkCalculate extends RecursiveTask<Integer>{
private Integer begin;
private Integer end;
public ForkCalculate(begin,end){
// 构造
}
protected Integer compute(){
if(end-begin <= 10){
// 已经划分到很细了,直接计算
}else{
int tmp = (begin+end)/2;
ForkCalculate t1 = new ForkCalculate(begin,tmp);
ForkCalculate t2 = new ForkCalculate(tmp+1,end);
t1.fork(); // 再次开启任务
t2.forl();
return t1.join()+t2.join();
}
}
}
class Test{
main(){
ForkCalculate cal = new ForkCalculate(0,100);
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask task = pool.submit(cal);
int sum = task.get();
}
}