1、JUC(java.util.concurrent) 是什么

在并发编程中使用的类

2、Lock 接口

3、Java8 之lamda表达式复习

拷贝小括号,写死右箭头, 落地大括号

4、线程间通信

判断
干活
通知

5、线程间定制化调用通信

1、高内聚前提下,线程操作资源类
2、判断 、 干活 、 通知
3、多线程交互中,必须要防止多线程的虚假唤醒,也即(判断只用while,不能用if)

JUC并发基础 - 图1

为什么使用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、线程池的参数

  1. public ThreadPoolExecutor(int corePoolSize,
  2. int maximumPoolSize,
  3. long keepAliveTime,
  4. TimeUnit unit,
  5. BlockingQueue<Runnable> workQueue,
  6. ThreadFactory threadFactory,
  7. RejectedExecutionHandler handler) {
  8. if (corePoolSize < 0 ||
  9. maximumPoolSize <= 0 ||
  10. maximumPoolSize < corePoolSize ||
  11. keepAliveTime < 0)
  12. throw new IllegalArgumentException();
  13. if (workQueue == null || threadFactory == null || handler == null)
  14. throw new NullPointerException();
  15. this.acc = System.getSecurityManager() == null ?
  16. null :
  17. AccessController.getContext();
  18. this.corePoolSize = corePoolSize;
  19. this.maximumPoolSize = maximumPoolSize;
  20. this.workQueue = workQueue;
  21. this.keepAliveTime = unit.toNanos(keepAliveTime);
  22. this.threadFactory = threadFactory;
  23. this.handler = handler;
  24. }

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、分支合并框架

  1. package com.wujing.juc.forkjoin;
  2. import java.util.concurrent.ExecutionException;
  3. import java.util.concurrent.ForkJoinPool;
  4. import java.util.concurrent.ForkJoinTask;
  5. import java.util.concurrent.RecursiveTask;
  6. /**
  7. * @author liuJieXin
  8. * @version v1.0
  9. * @className: ForkJoinDemo
  10. * @description <p> ForkJoin 测试 </p>
  11. * @date 2022/5/24 22:33
  12. */
  13. public class ForkJoinDemo {
  14. public static void main(String[] args) throws ExecutionException, InterruptedException {
  15. int end = 1000000;
  16. MyTask myTask = new MyTask(1, end);
  17. long start = System.currentTimeMillis();
  18. ForkJoinPool forkJoinPool = new ForkJoinPool();
  19. ForkJoinTask<Integer> submit = forkJoinPool.submit(myTask);
  20. System.out.println(submit.get());
  21. forkJoinPool.shutdown();
  22. System.out.println(System.currentTimeMillis() - start);
  23. long start1 = System.currentTimeMillis();
  24. int result = 0;
  25. for (int i = 1; i <= end; i++) {
  26. result += i;
  27. }
  28. System.out.println(result);
  29. System.out.println(System.currentTimeMillis() - start1);
  30. }
  31. }
  32. class MyTask extends RecursiveTask<Integer>{
  33. private static final Integer ADJUST_VALUE = 10;
  34. private int begin;
  35. private int end;
  36. private int result;
  37. public MyTask(Integer begin, Integer end) {
  38. this.begin = begin;
  39. this.end = end;
  40. }
  41. @Override
  42. protected Integer compute() {
  43. if((end - begin) <= ADJUST_VALUE){
  44. for (int i = begin ; i <= end; i++) {
  45. result = result + i;
  46. }
  47. }else {
  48. int middle = (end + begin) /2;
  49. MyTask myTask1 = new MyTask(begin, middle);
  50. MyTask myTask2 = new MyTask(middle+1, end);
  51. myTask1.fork();
  52. myTask2.fork();
  53. // System.out.println(myTask1.join());
  54. // System.out.println(myTask2.join());
  55. result = myTask1.join() + myTask2.join();
  56. }
  57. return result;
  58. }
  59. }

15、异步回调