java创建线程池的7种实现方法

 更新时间:2023年10月10日 16:38:45   作者:无形风  
在Java中线程池是一种管理线程的机制,它可以创建一组线程并重复使用它们,避免了创建和销毁线程的开销,这篇文章主要给大家介绍了关于java创建线程池的7种实现方法,需要的朋友可以参考下

这 7 种实现方法分别是:

  • Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。
  • Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
  • Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序。
  • Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池。
  • Executors.newSingleThreadScheduledExecutor:创建一个单线程的可以执行延迟任务的线程池。
  • Executors.newWorkStealingPool:创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】。
  • ThreadPoolExecutor:手动创建线程池的方式,它创建时最多可以设置 7 个参数。

一、用ExecutorService创建线程池

//1.创建一个大小为10的线程池
ExecutorService threadPool= Executors.newFixedThreadPool(10);
//给线程池添加任务
for (int i = 0;i < 10;i++){
    threadPool.submit(new Runnable() {
      @Override
      public synchronized void run(){
          //这里写你的方法
          log.info("开启线程..");
      }
  });
}

二、用ThreadPoolExecutor创建线程池

//1.创建一个大小为10的线程池
BlockingQueue queue = new LinkedBlockingQueue();
ThreadPoolExecutor executor= new ThreadPoolExecutor(10,Integer.MAX_VALUE,10L, TimeUnit.SECONDS,queue);
//给线程池添加任务
for (int i = 0;i < 10;i++){
executor.execute(new Runnable() {
    @Override
      public synchronized void run(){
          //这里写你的方法
          log.info("开启线程..");
      }
  });
}

从根本上说ExecutorService算是通过ThreadPoolExecutor封装出来的他们的底层其实是一样的

ThreadPoolExecutor需要传参,而ExecutorService有默认值,值需要一个线程数量就可以了。

三、用ThreadPoolUtils工具类创建线程池

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
 * 自定义线程创建工具类,创建线程池后不需要关闭
 *
 * @author liangxn
 */
public class ThreadPoolUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolUtils.class);
    private static ThreadPoolExecutor threadPool = null;
    private static final String POOL_NAME = "myPool";
    // 等待队列长度
    private static final int BLOCKING_QUEUE_LENGTH = 1000;
    // 闲置线程存活时间
    private static final int KEEP_ALIVE_TIME = 5 * 1000;
    private ThreadPoolUtils() {
        throw new IllegalStateException("utility class");
    }
    /**
     * 无返回值直接执行
     *
     * @param runnable 需要运行的任务
     */
    public static void execute(Runnable runnable) {
        getThreadPool().execute(runnable);
    }
    /**
     * 有返回值执行
     * 主线程中使用Future.get()获取返回值时,会阻塞主线程,直到任务执行完毕
     *
     * @param callable 需要运行的任务
     */
    public static <T> Future<T> submit(Callable<T> callable) {
        return getThreadPool().submit(callable);
    }
    /**
     * 停止线程池所有任务
     * @return
     */
    public static synchronized void shutdownNow() {
        getThreadPool().shutdownNow();
    }
    /**
     * 获取线程池中活跃线程数
     * @return
     */
    public static int getActiveCount() {
        return getThreadPool().getActiveCount();
    }
    private static synchronized ThreadPoolExecutor getThreadPool() {
        if (threadPool == null) {
            // 获取处理器数量
            int cpuNum = Runtime.getRuntime().availableProcessors();
            // 根据cpu数量,计算出合理的线程并发数
            int maximumPoolSize = cpuNum * 2 + 1;
            // 核心线程数、最大线程数、闲置线程存活时间、时间单位、线程队列、线程工厂、当前线程数已经超过最大线程数时的异常处理策略
            threadPool = new ThreadPoolExecutor(maximumPoolSize - 1,
                    maximumPoolSize,
                    KEEP_ALIVE_TIME,
                    TimeUnit.MILLISECONDS,
                    new LinkedBlockingDeque<>(BLOCKING_QUEUE_LENGTH),
                    new ThreadFactoryBuilder().setNameFormat(POOL_NAME + "-%d").build(),
                    new ThreadPoolExecutor.AbortPolicy() {
                        @Override
                        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                            LOGGER.warn("线程爆炸了,当前运行线程总数:{},活动线程数:{}。等待队列已满,等待运行任务数:{}",
                                    e.getPoolSize(),
                                    e.getActiveCount(),
                                    e.getQueue().size());
                        }
                    });
        }
        return threadPool;
    }
}

总结 

到此这篇关于java创建线程池的7种实现方法的文章就介绍到这了,更多相关java创建线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Feign调用时添加验证信息token到请求头方式

    使用Feign调用时添加验证信息token到请求头方式

    这篇文章主要介绍了使用Feign调用时添加验证信息token到请求头方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • java8中的lambda表达式,看这篇绝对够

    java8中的lambda表达式,看这篇绝对够

    这篇文章主要介绍了java8中的lambda表达式,看这篇绝对够!具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 一文带你掌握Spring Security框架的使用

    一文带你掌握Spring Security框架的使用

    Spring Security是一款基于Spring框架的认证和授权框架,提供了一系列控制访问和保护应用程序的功能,本文将会对Spring Security框架进行全面详细的讲解,需要的可以参考下
    2023-05-05
  • Java用Arrays.fill()初始化二维数组的实现

    Java用Arrays.fill()初始化二维数组的实现

    这篇文章主要介绍了Java用Arrays.fill()初始化二维数组的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • springboot配置文件读取pom文件信息方式

    springboot配置文件读取pom文件信息方式

    这篇文章主要介绍了springboot配置文件读取pom文件信息方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Java进阶之Object类及常用方法详解

    Java进阶之Object类及常用方法详解

    Object 类是 Java 默认提供的一个类,是所有 Java 类的祖先类,每个类都使用 Object 作为父类。本文就来和大家聊聊Object类的常用方法,希望对大家有所帮助
    2023-01-01
  • Java中Scanner用法实例解析

    Java中Scanner用法实例解析

    Scanner 指的是java.util包下的Scanner类,可以接收控制台输入的数据,下面这篇文章主要给大家介绍了关于Java中Scanner用法实例的相关资料,文中通过实例代码以及图文介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • 《阿里巴巴 Java开发手册》读后感小结

    《阿里巴巴 Java开发手册》读后感小结

    这篇文章主要介绍了《阿里巴巴 Java开发手册》读后感小结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • @Async导致controller 404及失效原因解决分析

    @Async导致controller 404及失效原因解决分析

    这篇文章主要为大家介绍了@Async导致controller 404失效问题解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • Java 中如何创建按钮单击事件

    Java 中如何创建按钮单击事件

    我们使用事件侦听器在Java中创建按钮单击事件,本文给大家讲解Java中的按钮单击事件,结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05

最新评论