管程
Monitor 监视器 (也就是锁)
是一种 同步机制, 能够保证 在 同一时间下, 只有 一个线程访问被保护数据 或者 代码
jvm 同步 基于 进入和退出, 使用 管程对象 实现
用户线程 : 自定义线程,
守护线程 : 如垃圾回收 ,运行在后台的 线程
主线程结束了,用户线程 还在运行, jvm存活
没有用户线程,都是守护线程, jvm结束
线程间的通信

package com.ma.other;
class Number{
//初始值
private int number=0;
//+1
public synchronized void incr() throws InterruptedException {
//判断 干活 通知
if (number !=0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+" ::"+ number);
this.notifyAll();
}
//-1
public synchronized void decr() throws InterruptedException {
//判断 干活 通知
if (number !=1){
//等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+" ::"+ number);
this.notifyAll();
}
}
public class ThredSynchronizeTest {
public static void main(String[] args) {
Number number=new Number();
new Thread(()->{
try {
for (int i = 0; i <10 ; i++) {
number.incr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"AA").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
number.decr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"BB").start();
}
}
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
AA ::1 BB ::0
wait()
对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在 循环中 使用
如果使用 if 判断的话,可能会产生虚假唤醒问题,故使用 while

package com.ma.other;
class Number{
//初始值
private int number=0;
//+1
public synchronized void incr() throws InterruptedException {
//判断 干活 通知
while (number !=0){
//等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+" ::"+ number);
this.notifyAll();
}
//-1
public synchronized void decr() throws InterruptedException {
//判断 干活 通知
while (number !=1){
//等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+" ::"+ number);
this.notifyAll();
}
}
public class ThredSynchronizeTest {
public static void main(String[] args) {
Number number=new Number();
new Thread(()->{
try {
for (int i = 0; i <10 ; i++) {
number.incr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"AA").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
number.decr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"BB").start();
new Thread(()->{
try {
for (int i = 0; i <10 ; i++) {
number.incr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"CC").start();
new Thread(()->{
try {
for (int i = 0; i < 10; i++) {
number.decr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"DD").start();
}
}


//使用lock
private Lock lock=new ReentrantLock();
//使用lock唤醒
private Condition condition=lock.newCondition();
//线程唤醒
// condition.signal();
condition.signalAll();
//上锁
lock.lock();
//线程等待
condition.await();
package com.ma.other.lock;
import lombok.SneakyThrows;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Number{
//初始值
private int number=0;
//使用lock
private Lock lock=new ReentrantLock();
//使用lock唤醒
private Condition condition=lock.newCondition();
@SneakyThrows
public void incr(){
//上锁
lock.lock();
try {
//防止线程唤醒问题
while (number !=0){
//线程等待
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+" ::"+ number);
//线程唤醒
// condition.signal();
condition.signalAll();
}finally {
lock.unlock();
}
}
public void decr() throws InterruptedException {
//上锁
lock.lock();
try {
//防止线程唤醒问题
while (number !=1){
//线程等待
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+" ::"+ number);
//线程唤醒
// condition.signal();
condition.signalAll();
}finally {
lock.unlock();
}
}
}
public class ThreadReentrantLockTest {
public static void main(String[] args) throws InterruptedException {
Number number = new Number();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
number.incr();
}
},"AA").start();
new Thread(()->{
try {
for (int i = 0; i <10 ; i++) {
number.decr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"BB").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
number.incr();
}
},"CC").start();
new Thread(()->{
try {
for (int i = 0; i <10 ; i++) {
number.decr();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
},"CC").start();
}
}
线程间的定制化通信


package com.ma.other.DIY;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//定义资源类
class DIY{
//标志符 flag 1 AA 2 BB 3 CC
private int flag=1;
//锁
private Lock lock=new ReentrantLock();
//3个锁
private Condition c1=lock.newCondition();
private Condition c2=lock.newCondition();
private Condition c3=lock.newCondition();
//打印5次,参数第几轮
public void print5(int loop) throws InterruptedException {
//上锁
lock.lock();
try{//判断
if (flag !=1)
{
//线程等待
c1.await();
}
//干活
for (int i = 1; i <=5; i++) {
System.out.println(Thread.currentThread().getName()+"::"+i+"::轮数"+loop);
}
flag=2;
//通知
c2.signal();
}finally {
lock.unlock();
}
}
//打印10次,参数第几轮
public void print10(int loop) throws InterruptedException {
//上锁
lock.lock();
try{//判断
if (flag !=2)
{
//线程等待
c2.await();
}
//干活
for (int i = 1; i <=10; i++) {
System.out.println(Thread.currentThread().getName()+"::"+i+"::轮数"+loop);
}
flag=3;
//通知
c3.signal();
}finally {
lock.unlock();
}
}
//打印15次,参数第几轮
public void print15(int loop) throws InterruptedException {
//上锁
lock.lock();
try{//判断
if (flag !=3)
{
//线程等待
c3.await();
}
//干活
for (int i = 1; i <=15; i++) {
System.out.println(Thread.currentThread().getName()+"::"+i+"::轮数"+loop);
}
flag=1;
//通知
c1.signal();
}finally {
lock.unlock();
}
}
}
public class DIYThreadTest {
public static void main(String[] args) {
DIY diy=new DIY();
new Thread(()->{
for (int i = 1; i <=10 ; i++) {
try {
diy.print5(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"AA").start();
new Thread(()->{
for (int i = 1; i <=10 ; i++) {
try {
diy.print10(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"BB").start();
new Thread(()->{
for (int i = 1; i <=10 ; i++) {
try {
diy.print15(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"CC").start();
}
}
AA::1::轮数1 AA::2::轮数1 AA::3::轮数1 AA::4::轮数1 AA::5::轮数1
BB::1::轮数1 BB::2::轮数1 BB::3::轮数1 BB::4::轮数1 BB::5::轮数1
BB::6::轮数1 BB::7::轮数1 BB::8::轮数1 BB::9::轮数1 BB::10::轮数1
CC::1::轮数1 CC::2::轮数1 CC::3::轮数1 CC::4::轮数1 CC::5::轮数1
CC::6::轮数1 CC::7::轮数1 CC::8::轮数1 CC::9::轮数1 CC::10::轮数1
CC::11::轮数1 CC::12::轮数1 CC::13::轮数1 CC::14::轮数1 CC::15::轮数1
集合线程安全
不安全的集合在多线程的情况下 插入数据 会出现 并发修改异常
ConcurrentModificationException,原因是在 使用 添加方法的时候没有加锁的操作
(在取的过程中, 数据没存储成功,或者在并发过程中多个线程)
三种解决方案
1、Vector 2、collections 3、CopyOnWriteArrayList
Vector 在add方法上 使用了 synchronized 关键字
Collections.synchronizedxxx 方法 static修饰
CopyOnWriteArrayList解决
CopyOnWriteArrayList 底层原理
写时复制技术

add() 实现了 lock接口 进行乐观锁的操作
在得到数组和数组长度之前 进行 加锁操作
之后 把 数组内容 进行 复制
然后往 新数组 写入 内容
之后 合并 之前的数组
使用 finally 进行 解锁操作
HastSet 使用 CopyOnWriteArraySet 解决
值 就是 Map的 key 无序 唯一
HashMap 使用 ConcurrentHashMap 解决
多线程 锁
synchronized 情况

公平锁和非公平锁
公平锁 效率高
多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。
优点:所有的线程都能得到资源,不会饿死在队列中。
缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。
非公平锁 线程实现抢占式
会造成 线程 饿死的情况 效率低
多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。
优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。
缺点:你们可能也发现了,这样可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死。
可重入锁(递归锁)
synchronized(隐式) Lock(显式) 都是可重入锁
隐式: 自动进行 加锁和解锁操作
显式:需要手动进行 加锁和解锁操作
可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。
package com.ma.other.syc;
public class SynOver {
public synchronized void add(){
add();
}
public static void main(String[] args) {
Object o=new Object();
new Thread(()->{
synchronized(o){
System.out.println("外层");
synchronized(o){
System.out.println("中层");
synchronized(o){
System.out.println("内层");
new SynOver().add();
}
}
}
}).start();
}
}
由于 synchronized 是可重入锁, 一直执行 add ()方法导致 栈溢出异常
package com.ma.other.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockOver {
public static void main(String[] args) {
Lock lock=new ReentrantLock();
new Thread(()->{
lock.lock();
System.out.println("上锁啦");
try{
lock.lock();
System.out.println("又上锁啦");
}finally {
// lock.unlock();
// System.out.println("解锁啦");
}
}).start();
new Thread(()->{
lock.lock();
System.out.println("上锁啦");
try{
lock.lock();
System.out.println("又上锁啦");
}finally {
lock.unlock();
System.out.println("解锁啦");
}
}).start();
}
}
如果不进行解锁操作, 就会导致 其他线程获取不到锁的情况
死锁
两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

package com.ma.other.dead;
/**
* 手写死锁
*/
public class LockDead {
public static void main(String[] args) {
Object o1 =new Object();
Object o2 =new Object();
new Thread(()->{
synchronized(o1){
System.out.println("获取o1锁");
System.out.println("释放o1锁");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o2){
System.out.println("获取o2锁");
System.out.println("释放o2锁");
}
}
}).start();
new Thread(()->{
synchronized(o2){
System.out.println("获取o2锁");
System.out.println("释放o2锁");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o1){
System.out.println("获取o1锁");
System.out.println("释放o1锁");
}
}
}).start();
}
}
由于 线程1 去获取o1锁 ,尝试获取o2锁,
线程2 去获取o2锁 ,尝试获取o1锁,导致 互相抢夺锁,而且不释放锁导致 死锁的情况
3.如何 验证 死锁
1、 jps 类似于 linxu ps -ef 查询进程
2、 jstack jvm自带 堆栈跟踪工具
先 jps -l

在 jstack 6252




Boolean isDone() 返回线程是否完成
T get() 返回线程值
单开启一个线程,在不影响主线程的情况下,做其他任务

package com.ma.other.runcall;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
class run implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"run");
}
}
class call implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName()+"CALL");
return 200;
}
}
public class Futch {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Thread thread=new Thread(new run(),"AA");
thread.start();
FutureTask<Integer> futureTask1=new FutureTask<Integer>(new call());
//lam表达式
FutureTask<Integer> futureTask2=new FutureTask<Integer>(()->{
return 2020;
});
new Thread(futureTask2,"ss").start();
new Thread(futureTask1,"ll").start();
while (!futureTask2.isDone()){
System.out.println("wait....");
}
System.out.println(futureTask2.get());
}
}
辅助类 AQS提供的
减少计数 CountDownLath
循环栅栏 CyclicBarrier
信号灯 Semaphore
计数器 CountDownLath



package com.ma.other.AQS;
import java.util.concurrent.CountDownLatch;
/*
CountDownLath 演示
6个同学陆续离开教室,班长才锁门
*/
public class CountDownLathDemo {
public static void main(String[] args) {
//初始CountDownLath 值为6
CountDownLatch countDownLatch=new CountDownLatch(6);
//6个同学离开教室
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"号同学离开教室");
//当同学离开 计数器-1
countDownLatch.countDown();
},String.valueOf(i)).start();
}
//当计数器 不为0 , 班长等待 不锁门
try {
countDownLatch.await();
System.out.println(Thread.currentThread().getName()+"班长离开教室");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
计数器初始值 为 6 ,每次 线程执行完 -1 ,当 计数器 值 不为 0时候,主线程 进行 等待
countDownLatch.countDown(); 计数器值-1
countDownLatch.await(); 线程等待
循环栅栏 CyclicBarrier



package com.ma.other.AQS;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/*
CyclicBarrier 循环栅栏
集齐7个龙珠 实现 召唤神龙
*/
public class CyclicBarrierDemo {
private static int Number=7;
public static void main(String[] args) {
//创建 CyclicBarrier 对象
CyclicBarrier cyclicBarrier=new CyclicBarrier(
Number,()->{
System.out.println("集齐7个龙珠 实现 召唤神龙");
}
);
for (int i = 1; i <=7 ; i++) {
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"颗龙珠");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
},String.valueOf(i)).start();
}
}
}

信号灯 Semaphore




package com.ma.other.AQS;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/*
6辆车 抢占3个车位
*/
public class SemaphoreDemo {
public static void main(String[] args) {
//创建Semaphore对象 创建3个车位
Semaphore semaphore=new Semaphore(3);
//创建6个线程
for (int i = 1; i <6 ; i++) {
new Thread(()->{
//抢占车位
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"号抢到车位");
//设置随机随机
// TimeUnit.SECONDS.sleep(new Random().nextInt(5));
Thread.sleep(new Random().nextInt(5));
System.out.println(Thread.currentThread().getName()+"离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
},String.valueOf(i)).start();
}
}
}
读写锁
ReentrantReadWriteLock

package com.ma.other.readWrite;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
//创建资源类
class Mapgetput{
public volatile Map<String,Object> map=new HashMap<>();
private ReadWriteLock readWriteLock=new ReentrantReadWriteLock();
final Lock lock = readWriteLock.writeLock();
final Lock lock2 = readWriteLock.readLock();
//写操作
public void put(String key,Object o){
lock.lock();
try {
System.out.println(Thread.currentThread().getName()+"正在写操作"+key);
//暂停一会
Thread.sleep(300);
//放数据
map.put(key,o);
System.out.println(Thread.currentThread().getName()+"写完操作"+key);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
//读操作
public void get(String key){
lock2.lock();
try {
System.out.println(Thread.currentThread().getName()+"正在读操作"+key);
Thread.sleep(300);
//放数据
map.get(key);
System.out.println(Thread.currentThread().getName()+"读完操作"+key);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock2.unlock();
}
}
}
public class readWrite {
public static void main(String[] args) {
Mapgetput mapgetput=new Mapgetput();
for (int i = 1; i <=5 ; i++) {
final int num=i;
new Thread(()->{
{
mapgetput.put(num+"",num);
}
},String.valueOf(i)).start();
}
for (int i = 1; i <=5 ; i++) {
final int num=i;
new Thread(()->{
{
mapgetput.get(num+"");
}
},String.valueOf(i)).start();
}
}
}

读写锁深入
读写锁: 一个资源可以被多个 读线程访问, 或者可以被 一个写线程访问,但是不能同时存在 读写线程,读写互斥, 读读共享
锁降级:
将写入锁 降为 读锁
jdk8的步骤
获取写锁 —> 获取读锁 ----> 释放写锁 —> 释放读锁
读锁 不能升级 为 写锁


package com.ma.other.readWrite;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/*
演示写锁 降为 写锁
*/
public class downLock {
public static void main(String[] args) {
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
final ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();//读锁
final ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();//写锁
writeLock.lock();
System.out.println("写锁");
readLock.lock();
System.out.println("读锁");
readLock.unlock();
System.out.println("释放读锁");
writeLock.unlock();
System.out.println("释放写锁");
}
}
写锁
读锁
释放读锁
释放写锁
堵塞队列
堵塞队列 是一个队列, 通过 一个 共享的队列 可以使得数据 由队列的一端输入, 由另一端输出
当队列为空 从队列中 获取元素的操作 将会被 堵塞
当队列为满 从队列中 添加元素的操作 将会被 堵塞
试图 向 已满的队列中 添加新元素 的 线程 将会被 堵塞
直到 其他线程 从 队列中 移除 一个 或 多个元素或者完全清空
使得队列变得空闲起来并后续新增

在多线程领域: 所谓堵塞, 在某些情况下 会挂起(即堵塞)
一旦条件满足,被挂起的线程 又会自动被唤醒
堵塞队列的架构
接口 BlockingQueue《E》

堵塞队列的分离 以及 核心方法
1.由 数组结构组成的 有界堵塞队列
ArrayBlockingQueue
-
由 链表结构组成的有界 (但大小 默认值 为 integer.MAX_VALUE)堵塞队列
LinkedBlockingDeque -
使用 优先级队列 实现 的 延迟无界阻塞队列
DelayQueue -
支持 优先级 排序 的无界 堵塞队列
PriorityBlockingQueue -
不存储 元素 的堵塞队列 也就是 单个元素的 队列
SynchronizedQueue -
由 链表组成的 无界堵塞队列
LinkedTransferQueue -
由 链表组成的 双向堵塞队列
LinkedBlockingDeque
堵塞队列的核心方法


package com.ma.other.Queue;
import java.util.concurrent.*;
public class BlockinQueueTest {
public static void main(String[] args) {
//创建堵塞队列
ArrayBlockingQueue<String> blockingDeque= new ArrayBlockingQueue<String>(3);
System.out.println(blockingDeque.add("a1"));
System.out.println(blockingDeque.add("a2"));
System.out.println(blockingDeque.add("a3"));
System.out.println(blockingDeque.element());
//System.out.println(blockingDeque.add("a4"));
System.out.println(blockingDeque.remove());
System.out.println(blockingDeque.remove());
System.out.println(blockingDeque.remove());
System.out.println(blockingDeque.remove());
}
}

线程池概述
一种线程使用模式, 线程过多会带来调度开销,进而影响 缓存局部性 和 整体性能。 而 线程池 维护着 多个线程 ,等待着 监督管理者 分配可并发执行的任务。
这避免了 在处理 短时间任务 时 创建 与 销毁线程的 代价
线程不仅 能够保证内核的 充分利用, 还能 防止过分调度。
优势:
线程池做的工作 只要是 控制 运行的线程数量, 处理过程中将 任务 放入队列, 然后在 线程创建后 启动 这些 任务, 如果 线程数量 超过了 最大数量, 超出 数量的 线程 排队等候,等 其他线程 执行完毕, 再从队列 中 取出来任务 来执行。
特点:
1、降低资源消耗
2、提高响应速度
3、提高线程的 可管理性

线程池使用方式
Executors. newFixedThreadPool(int) 一池N线程
特征:
- 线程池中的 线程 处于 一定的量 , 可以很好的 控制 线程的 并发量
- 线程可以重复被利用 在显示关闭之前, 都将一直存在
- 超出 一定量的 线程 被 提交时候 需在 队列中 等待
Executors. newSingleThreadExecutor()
一个任务 一个任务执行 一池一线程
Executors. newCachedThreadPool()
线程池根据需求创建线程, 可扩容, 遇强则强
newSingleThreadExecutor :创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
线程池的底层原理
都是通过 ThreadPoolExecutor 构造方法 进行创建
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
/*
演示线程池 三种常用分类
*/
public class ThreadPollTest {
public static void main(String[] args) {
//一池N线程
ExecutorService threadPool1= Executors.newFixedThreadPool(5);//5个线程
//一池一线程
ExecutorService threadPool2= Executors.newSingleThreadExecutor();
//根据需求自动创建线程数
ExecutorService threadPool3=Executors.newCachedThreadPool();
//根据优先级 创建一个单线程
ExecutorService threadPool4=Executors.newScheduledThreadPool(2);
try{
for (int i = 1; i <10 ; i++) {
threadPool4.execute(()->{
System.out.println(Thread.currentThread().getName()+"号办理业务");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程
threadPool4.shutdown();
}
}
}
线程池的七个参数
int corePoolSize, 核心线程数
int maximumPoolSize, 最大线程数量
long keepAliveTime,线程存活时间
TimeUnit unit,单位
BlockingQueue workQueue
堵塞队列
ThreadFactory threadFactory
线程工厂 用于 创建线程
RejectedExecutionHandler handler
拒绝策略
4个
abortPolicy : 直接抛出 RejectedExecutionException 异常
CallerRunsPolicy : 调用者模式
既不会 抛出异常 也不会放弃任务 , 而是将 任务 回退到 调用者,从而降低 新任务的流量
DiscardOldPolicy :
抛弃队列中 等待时间最久的 任务 然后把 任务加入 队列中 ,尝试再次提交 当前任务
DiscarPolicy :
不抛出异常 也不做任务处理 , 默默丢弃无法处理的任务
线程池的底层工作流程

自定义线程池

Fork / Join 分支合并框架
Fork/Join 它可以 将 一个大的任务 拆分成 多个 子任务 进行 并行处理,最后 将 子任务结果 合并成 最后的 计算结果, 并进行 输出。
Fork : 分支 把一个复杂的任务 进行分拆 大事化小
Join :合并 把分拆任务的结果 进行合并




package com.ma.other.pool;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class MyTask extends RecursiveTask<Integer> {
//拆分差值 不能超过10 , 计算 10 以内 运算
private static final Integer VALUE=10;
private int begin;
private int end;
private int result;
//创建有参构造
public MyTask(int begin, int end) {
this.begin = begin;
this.end = end;
}
//拆分和合并过程
protected Integer compute() {
//判断 相加 两数 数组 是否 大于 10
if ((end-begin) <= VALUE)
{
//相加操作
for (int i = begin; i <= end ; i++) {
result= result+i;
}
}
else {
//进一步拆分
//获取中间值
int middle= (begin + end ) /2 ;
//拆分左边
MyTask myTask1=new MyTask(begin,middle);
//拆分右边
MyTask myTask2=new MyTask(middle+1,end);
//调用方法拆分
myTask1.fork();
myTask2.fork();
//合并结果
result =myTask1.join() + myTask2.join();
}
return result;
}
}
class Test{
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建 MyTask对象
MyTask myTask=new MyTask(0,100);
// 创建分支合并池对象
ForkJoinPool forkJoinPool=new ForkJoinPool();
final ForkJoinTask<Integer> submit = forkJoinPool.submit(myTask);
final Integer integer = submit.get();
System.out.println(integer);
}
}
CompletableFuture 异步回调



被折叠的 条评论
为什么被折叠?



