0
点赞
收藏
分享

微信扫一扫

Java多线程​(六)线程池

线程池

基础知识

线程创建和启用会消耗系统资源,因此统一创建、管理和使用线程就显得非常有意义。我们把线程创建好好后放入线程池,需要时从这个池子中申请使用,使用完成后再还给线程池,线程的创建、管理、使用和消亡过程由线程池管理,这就是线程池的概念。

线程池主要核心原理

①创建一个池子,池子中是空的

②提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子

下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可

③但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待


线程池代码实现步骤

1,创建线程池

2,提交任务

3,所有的任务全部执行完毕,关闭线程池

线程池使用:


Executors工具类

Executors:线程池的工具类通过调用方法返回不同类型的线程池对象。

方法名称

说明

public static ExecutorServicenewCachedThreadPool()

创建一个没有上限的线程池

public static ExecutorService newFixedThreadPool(int nThreads)

创建有上限的线程池

Executors的执行原理:

①创建一个池子,池子中是空的

②提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可

③但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyThreadPoolDemo {
 public static void main(String[] args) {
 /*
 public static ExecutorService newCachedThreadPool() 创建一个没有上限的线程池
 public static ExecutorService newFixedThreadPool(int nThreads) 创建有上限的线程池
 */

 // 1.获取线程池对象
 ExecutorService pool1 = Executors.newCachedThreadPool();
 //ExecutorService pool1 = Executors.newFixedThreadPool(3); // 规定最大线程数量的池子

 // 2.提交任务
 // 第一种方式:直接实现方法接口
 /*
 pool1.submit(new Runnable() {
 @Override
 public void run() {
 for (int i = 0; i < 100; i++) {
 System.out.println(Thread.currentThread().getName() + "---" + i);
 }
 }
 });
 */
 // 第二种方式:传入Runnable接口或Callable实现类对象
 pool1.submit(new MyRunnable());
 pool1.submit(new MyRunnable());
 pool1.submit(new MyRunnable());
 pool1.submit(new MyRunnable());
 pool1.submit(new MyRunnable());

 // 3.销毁线程池
 pool1.shutdown();
 }
}

任务代码:

public class MyRunnable implements Runnable{
 @Override
 public void run() {
 for (int i = 0; i < 100; i++) {
 System.out.println(Thread.currentThread().getName() + "---" + i);
 //System.out.println(Thread.currentThread().getName() + "---");
 }
 }
}

自定义线程池ThreadPoolExecutor

用饭店的场景来理解线程池

Java多线程​(六)线程池_java


核心线程都在忙,且等待队伍满,还有任务提交则会创建临时线程开始处理这些新提交的任务。这里需要注意的是,原先已经在排队的任务不会被临时线程优先处理,而是继续等待核心线程忙完才会轮到排队的线程。如果临时线程也被用完,再提交的任务就会被抛弃(拒绝服务)。


任务拒绝策略

任务拒绝策略

说明

ThreadPoolExecutor.AbortPolicy

默认策略:丢弃任务并抛出RejectedExecutionException异常

ThreadPoolExecutor.DiscardPolicy

丢弃任务,但是不抛出异常这是不推荐的做法

ThreadPoolExecutor.DiscardoldestPolicy

抛弃队列中等待最久的任务然后把当前任务加入队列中

ThreadPoolExecutor.CallerRunsPolicy

调用任务的run()方法绕过线程池直接执行

不断的提交任务,会有以下三个临界点:

①当核心线程满时,再提交任务就会排队

②当核心线程满,队伍满时,会创建临时线程

③当核心线程满,队伍满,临时线程满时,会触发任务拒绝策略

使用线程池的代码:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyThreadPoolDemo1 {
 public static void main(String[] args) {
 /*
 ThreadPoolExecutor threadPoolExecutor =new ThreadPoolExecutor
 (核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);

 参数一:核心线程数量 不能小于θ
 参数二:最大线程数 不能小于等于θ,最大数量>=核心线程数量
参数三:空闲纸程最大存活时间 不能小于θ
 参数四:时间单位 用TimeUnit指定
参数五:任务队列 不能为null
 参数六:创建线程工厂 不能为null
 参数七:任务的拒绝策略 不能为null
 */
 ThreadPoolExecutor pool = new ThreadPoolExecutor(
 3, //核心线程数量,不能小于0
 6, //最大线程数,不能小于0,最大数量>=核心线程数量
 60, //空闲线程最大存货时间
 TimeUnit.SECONDS, //时间单位
 new ArrayBlockingQueue<>(3), //任务队列
 Executors.defaultThreadFactory(), //创建线程工厂
 new ThreadPoolExecutor.AbortPolicy() // 任务的拒绝策略
 );

 // 为线程池提交任务
 pool.submit(new Runnable() {
 @Override
 public void run() {
 // 任务执行代码
 }
 });
 }
}



线程池多大合适?

Java多线程​(六)线程池_java_02


I/O密集型可以使用thread dump进行辅助计算。




举报

相关推荐

0 条评论