java for循环改造多线程-线程池原理

通过ThreadPoolExecutor类自定义:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        // 省略...
    }

1、共7个参数如下:

(1)corePoolSize:核心线程数,线程池中始终存活的线程数。

(2)maximumPoolSize: 最大线程数,线程池中允许的最大线程数。

(3)keepAliveTime: 存活时间,线程没有任务执行时最多保持多久时间会终止。

(4)unit: 单位,参数keepAliveTime的时间单位,7种可选。

参数 描述
TimeUnit.DAYS
TimeUnit.HOURS 小时
TimeUnit.MINUTES
TimeUnit.SECONDS
TimeUnit.MILLISECONDS 毫秒
TimeUnit.MICROSECONDS 微妙
TimeUnit.NANOSECONDS 纳秒

(5)workQueue: 一个阻塞队列,用来存储等待执行的任务,均为线程安全,7种可选。

参数 描述
ArrayBlockingQueue 一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue 一个由链表结构组成的有界阻塞队列。
SynchronousQueue 一个不存储元素的阻塞队列,即直接提交给线程不保持它们。
PriorityBlockingQueue 一个支持优先级排序的无界阻塞队列。
DelayQueue 一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素。
LinkedTransferQueue 一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
LinkedBlockingDeque 一个由链表结构组成的双向阻塞队列。

较常用的是LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。

(6)threadFactory: 线程工厂,主要用来创建线程,默及正常优先级、非守护线程。

(7)handler:拒绝策略,拒绝处理任务时的策略,4种可选,默认为AbortPolicy。

参数 描述
AbortPolicy 拒绝并抛出异常。
CallerRunsPolicy 重试提交当前的任务,即再次调用运行该任务的execute()方法。
DiscardOldestPolicy 抛弃队列头部(最旧)的一个任务,并执行当前任务。
DiscardPolicy 抛弃当前任务。

 

2、顺便说下线程池的执行规则如下:

(1)当线程数小于核心线程数时,创建线程。

(2)当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。

(3)当线程数大于等于核心线程数,且任务队列已满:

若线程数小于最大线程数,创建线程。

若线程数等于最大线程数,抛出异常,拒绝任务。

示例代码:

package com.company;

import java.time.LocalDateTime;
import java.util.concurrent.*;

public class Main {

    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(5, 20,
                1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(100, true),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
            final int index = i;
            executorService.execute(() -> {
                // 获取线程名称,默认格式:pool-1-thread-1
                System.out.println(LocalDateTime.now() + " " + Thread.currentThread().getName() + " " + index);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

 

 
posted on 2023-01-21 21:18  武定路  阅读(616)  评论(0编辑  收藏  举报