ThreadPoolExercise1
java
package ThreadPoolExercise20240813;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExercise1 {
public static void main(String[] args) throws InterruptedException {
// 线程池
// 线程池,顾名思义,就像一个水池,水池中存储了大量的水;而线程池中可以存储大量的线程
/* 线程池的意义:
系统创建一个线程的成本相对较高,其涉及到与操作系统的交互,当程序中需要创建大量生命周期短暂的线程时
频繁的创建和销毁线程对于系统的资源是极大的消耗,甚至可能大于业务本身对于资源的消耗。所以说针对这种大量创建线程的
情况,就可以使用线程池------------线程池在启动时就会创建大量的空闲线程,当向线程池提交任务时(需要线程来完成这个任务),
线程池就会启动池内的一个线程来执行该任务,等待任务执行完成之后,线程并非直接死亡,而是再次返回线程池中,再次变为
空闲状态,等待下一次任务的执行(再一次申请线程执行任务) */
// 总结而言,线程池的意义主要是在于减少了线程的重复创建,通过线程池,线程可以重复利用,提高了效率
// 设计思路:
// 1.准备一个任务容器;
// 2.一次性启动多个(至少2个)消费者线程
// 3.刚开始任务容器是空的,所以说所有线程都是wait状态
// 4.直到外部线程向任务容器中添加一个"任务",就有一个消费者线程被唤醒来执行这个任务
// 5.消费者线程在任务容器中"取出"这个任务,然后执行这个任务,执行完毕后,继续等待下个任务
// Executors默认线程池
// JDK对线程池有默认实现------------Executors默认线程池,其实真实开发中也很少自定义线程池,大部分情况都是使用JDK默认线程池
// 创建线程池
// Executors静态方法创建
// static ExecutorsService newCachedThreadPool() 创建一个默认的线程池
// static newFixedThreadPool(int nThread) 创建一个指定最多线程数量的线程池
// 创建一个默认的线程池对象,默认是空的,默认最多可以容纳int类型的最大值的线程(理论有限、实际无限)
ExecutorService executorService = Executors.newCachedThreadPool();
// Executors ------------ 可以帮助创建默认线程池对象
// ExecutorService ------------ 可以帮助控制线程池
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行");
}
});
//Thread.sleep(2000);
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行");
}
});
// 调用shutdown方法关闭线程池
executorService.shutdown();
/* 注:假如在两个任务提交的间隔加入sleep方法,线程池中只会有一条线程被使用,因为在sleep的时候,执行任务1的线程1已经执行
完毕并返回线程池处于空闲状态,当任务2提交后,线程1处于空闲状态,所以说还是由线程1执行的任务2 */
}
}
ThreadPoolExercise2
java
package ThreadPoolExercise20240813;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadPoolExercise2 {
public static void main(String[] args) {
// static ExecutorService newFixedThreadPool(int nThread) 创建一个指定最多线程数的线程池
// 参数不是初始值而是最大值
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 如此处参数传递10,并非是线程的初始数目就是10,而是线程池中的最大线程数是10
ThreadPoolExecutor pool = (ThreadPoolExecutor) executorService;
System.out.println(pool.getPoolSize()); //0
// 可见最开始创建线程池,线程池中的线程是0
executorService.submit(()->{
System.out.println(Thread.currentThread().getName() + "在执行了");
});
executorService.submit(()->{
System.out.println(Thread.currentThread().getName() + "在执行了");
});
System.out.println(pool.getPoolSize()); //2
executorService.shutdown();
}
}
ThreadExercise3
java
package ThreadPoolExercise20240813;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExercise3 {
public static void main(String[] args) {
// ThreadPoolExecutor自定义线程池
// 创建线程池对象
// ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1.核心线程的数量 int corePoolSize
// 2.最大线程的数量 int maximumPoolSize
// 3.空闲线程的最大存活时间 long keepAliveTime
// 4.时间单位 TimeUnit unit
// 5.任务队列 BlockingQueue<Runnable> workQueue
// 6.创建线程工厂 ThreadFactory threadFactory
// 7.任务的拒绝策略) RejectedExecutionHandler handler
// 各个参数的要求:
// 1.核心线程数量:不能小于0
// 2.最大线程数量:不能≤0,最大数量≥核心线程数量
// 3.空闲线程的最大存活时间:不能小于0
// 4.时间单位:正确的时间单位
// 5.任务队列:不能为null
// 6.创建线程工厂:不能为null
// 7.任务的拒绝策略:不能为null
// 非默认的任务拒绝策略
// RejectedExecutionHandler 是JDK提供的一个任务拒绝策略的接口,存在以下子类:
/*
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。是默认的策略。
ThreadPoolExecutor.DiscardPolicy: 丢弃任务,但是不抛出异常 这是不推荐的做法。
ThreadPoolExecutor.DiscardOldestPolicy: 抛弃队列中等待最久的任务 然后把当前任务加入队列中。
ThreadPoolExecutor.CallerRunsPolicy: 调用任务的run()方法绕过线程池直接执行。
*/
/*
核心线程数量为1 , 最大线程池数量为3, 任务容器的容量为1 ,空闲线程的最大存在时间为20s
*/
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1 , 3 , 20 , TimeUnit.SECONDS ,
new ArrayBlockingQueue<>(1) , Executors.defaultThreadFactory() , new ThreadPoolExecutor.AbortPolicy()) ;
// 线程池最大可执行任务数 = 队列容量 + 最大线程数
// 提交5个任务,而该线程池最多可以处理4个任务,当我们使用AbortPolicy这个任务处理策略的时候,就会抛出异常
for(int x = 0 ; x < 5 ; x++) {
threadPoolExecutor.submit(() -> {
System.out.println(Thread.currentThread().getName() + "---->> 执行了任务");
});
}
// 一共有4个线程执行了任务,到了第五个任务时,抛出异常
}
}