- 1、JUC(java.util.concurrent) 是什么
- 2、Lock 接口
- 3、Java8 之lamda表达式复习
- 4、线程间通信
- 5、线程间定制化调用通信
- 6、NotSafeDemo
- 7、多线程锁
- 8、Callable接口
- 9、JUC 强大的辅助
- 10、ReentrantReadWriteLock 读写锁
- 11、BlockingQueueDemo 阻塞队列
- 12、ThreadPool线程池
- 1、线程池的参数
- 1.1 int corePoolSize : 线程池中的常驻核心 线程数
- 1.2 int maximumPoolSize : 线程池中能够容纳同时 执行的最大线程数,此值必须大于等于1
- 1.3 long keepAliveTime : 多余的空闲线程的存活时间,当前池中线程数量超过corePoolSize时,当空闲时间到达keepAliveTime时,多余线程会被销毁直到只剩余corePoolSize个线程为止
- 1.4 TimeUnit unit :keepAliveTime 的单位
- 1.5 BlockingQueue
workQueue : 任务队列,被提交但尚未被执行的任务 - 1.6 ThreadFactory threadFactory :表示生成线程池中工作线程的线程工厂,用于创建线程,一般默认即可。
- 1.7 RejectedExecutionHandler handler:拒绝策略,表示当队列 满了,并且工作线程大于等于线程池的最大线程数(maximumPoolSize) 时如何来拒绝请求执行的runnable 的策略
- 2、线程池的原理
- 3、线程用哪个?如何设置合理参数
- 1、线程池的参数
- 13、Java8之流式计算
- 14、分支合并框架
- 15、异步回调
1、JUC(java.util.concurrent) 是什么
在并发编程中使用的类
2、Lock 接口
3、Java8 之lamda表达式复习
4、线程间通信
5、线程间定制化调用通信
1、高内聚前提下,线程操作资源类
2、判断 、 干活 、 通知
3、多线程交互中,必须要防止多线程的虚假唤醒,也即(判断只用while,不能用if)
�
为什么使用lock
Lock8锁
6、NotSafeDemo
集合类是不安全的
ConcurrentModificationException
1、导致原因
2、解决方案
1)使用Vector
2) 使用 Collections 工具类
3)JUC 包中,CopyOnWriteArrayList
�
3、优化建议(同样的错误,不出现第2次)
7、多线程锁
8、Callable接口
9、JUC 强大的辅助
10、ReentrantReadWriteLock 读写锁
11、BlockingQueueDemo 阻塞队列
12、ThreadPool线程池
1、线程池的参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
1.1 int corePoolSize : 线程池中的常驻核心 线程数
1.2 int maximumPoolSize : 线程池中能够容纳同时 执行的最大线程数,此值必须大于等于1
1.3 long keepAliveTime : 多余的空闲线程的存活时间,当前池中线程数量超过corePoolSize时,当空闲时间到达keepAliveTime时,多余线程会被销毁直到只剩余corePoolSize个线程为止
1.4 TimeUnit unit :keepAliveTime 的单位
1.5 BlockingQueue workQueue : 任务队列,被提交但尚未被执行的任务
1.6 ThreadFactory threadFactory :表示生成线程池中工作线程的线程工厂,用于创建线程,一般默认即可。
1.7 RejectedExecutionHandler handler:拒绝策略,表示当队列 满了,并且工作线程大于等于线程池的最大线程数(maximumPoolSize) 时如何来拒绝请求执行的runnable 的策略
2、线程池的原理
1、在创建了线程池后,开始等待请求。
2、当调用execute()方法添加一个请求任务时,线程池会做出如下判断:
2.1如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;
2.2如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列;
2.3如果这个时候队列满了且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;
2.4如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行。
3、当一个线程完成任务时,它会从队列中取下一个任务来执行。
4、当一个线程无事可做超过一定的时间(keepAliveTime)时,线程会判断:
如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。
所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小。
3、线程用哪个?如何设置合理参数
13、Java8之流式计算
14、分支合并框架
package com.wujing.juc.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
/**
* @author liuJieXin
* @version v1.0
* @className: ForkJoinDemo
* @description <p> ForkJoin 测试 </p>
* @date 2022/5/24 22:33
*/
public class ForkJoinDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
int end = 1000000;
MyTask myTask = new MyTask(1, end);
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Integer> submit = forkJoinPool.submit(myTask);
System.out.println(submit.get());
forkJoinPool.shutdown();
System.out.println(System.currentTimeMillis() - start);
long start1 = System.currentTimeMillis();
int result = 0;
for (int i = 1; i <= end; i++) {
result += i;
}
System.out.println(result);
System.out.println(System.currentTimeMillis() - start1);
}
}
class MyTask extends RecursiveTask<Integer>{
private static final Integer ADJUST_VALUE = 10;
private int begin;
private int end;
private int result;
public MyTask(Integer begin, Integer end) {
this.begin = begin;
this.end = end;
}
@Override
protected Integer compute() {
if((end - begin) <= ADJUST_VALUE){
for (int i = begin ; i <= end; i++) {
result = result + i;
}
}else {
int middle = (end + begin) /2;
MyTask myTask1 = new MyTask(begin, middle);
MyTask myTask2 = new MyTask(middle+1, end);
myTask1.fork();
myTask2.fork();
// System.out.println(myTask1.join());
// System.out.println(myTask2.join());
result = myTask1.join() + myTask2.join();
}
return result;
}
}