美文网首页
java中创建线程池的方式

java中创建线程池的方式

作者: 缘木与鱼 | 来源:发表于2019-09-30 16:04 被阅读0次

    创建线程池的方式:

    使用Java提供的用于管理线程池的接口ExecutorService 创建线程池,共有四种方式:

    Executors.newCachedThreadPool();
    Executors.newFixedThreadPool(10);
    Executors.newScheduledThreadPool(10);
    Executors.newSingleThreadExecutor();
    
    // 获取当前主机的处理器cpu的可用个数,可根据该参数来修改线程池的大小
    System.out.println("处理器的可用个数:" + Runtime.getRuntime().availableProcessors());
    

    1、 newCachedThreadPool

    创建一个可根据需要创建新线程的线程池,在以前创建的线程可用时重用它们。该线程池可缓存,无限大。

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getId());
                }
            });
        }
    }
    

    源码:

    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
    }
    
    // 上面返回的对象指向下面的 ThreadPoolExecutor(...) 构造方法
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    

    参数的意义:

    • corePoolSize :核心线程池的数量
    • maximumPoolSize :线程池的最大数量, Integer.MAX_VALUE 可以看作是无限的
    • keepAliveTime : 线程保持活跃状态的时间
    • unit : 时间单位
    • workQueue : 工作队列,SynchronousQueue 是一个不存储元素的队列,可以理解为队列已满

    根据上面的源码可知:
    当调用该方法创建线程池时,workQueue 为0,不创建核心线程,且队列已满,因此会创建非核心线程执行任务。对于非核心线程空闲60s就会被回收,而线程池的数量几乎是无限的,当资源有限时易引起OOM异常。

    2、newFixedThreadPool

    创建一个可重用固定线程集合的线程池,以共享的无界队列方式运行线程。
    定长的线程池,可控制线程最大并发数,超出的线程会在队列中等待。

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getId());
                }
            });
        }
    }
    

    源码:

    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
    }
    
    
    // 上面返回的对象指向下面的 ThreadPoolExecutor(...) 构造方法
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
    

    说明

    参数与SingleThreadExecutor 一致,区别是核心线程数是由用户传入的。

    3、newSingleThreadExecutor

    创建一个使用单个worker线程的线程池,以无界队列的方式运行。
    该线程池只存在一个线程,会按照顺序执行,不同与单线程。

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getId());
                }
            });
        }
    }
    

    源码:

    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
    }
    
    // 上面返回的对象指向下面的 ThreadPoolExecutor(...) 构造方法
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    

    说明

    返回的核心线程池数量为1,最大线程池数量为1,即只能创建一个非核心线程。

    4、newScheduledThreadPool

    创建一个线程池,可安排在给定延迟后运行命令或定期执行。
    定长线的程池,支持定时及周期性任务执行。

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newScheduledThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getId());
                }
            });
        }
    }
    

    源码:

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
    // 上面返回的对象指向下面的构造方法
    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
    
    // 查看ScheduledThreadPoolExecutor 的类,发现其继承了ThreadPoolExecutor,并实现了ScheduledExecutorService接口
    public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {...}
    
    
    // 继续追踪父类的构造方法
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
    // this(...)方法对应的如下:
    public ThreadPoolExecutor(int corePoolSize,         // 核心线程池数量
                              int maximumPoolSize,      // 最大线程数
                              long keepAliveTime,       // 保持线程存活时间
                              TimeUnit unit,            // 时间单位
                              BlockingQueue<Runnable> workQueue,     // 保存任务的阻塞队列
                              ThreadFactory threadFactory,         // 创建线程的工厂
                              RejectedExecutionHandler handler) {     // 拒接策略
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
    

    其他方式

    // 通过ScheduledExecutorService(继承了ExecutorService)接口,调用schedule方法,通过该方法中的参数设置可以设置执行时间。
    // 该方法的第二个、第三个参数结合设置从当前开始推迟设置的时间来执行
    public static void main(String[] args) {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        for (int i = 0; i < 10; i++) {
            scheduledThreadPool.schedule(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getId());
                }
            }, 3, TimeUnit.SECONDS);
        }
    }
    

    相关文章

      网友评论

          本文标题:java中创建线程池的方式

          本文链接:https://www.haomeiwen.com/subject/kgqhpctx.html