线程池

我们可以查看线程池的源码,然后查看到最顶端,Executor是一个接口,需要实现。

public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

点下去看又有ExecutorService继承Executor,可是ExecutorService依旧是接口。

public interface ExecutorService extends Executor

再继续点下去(IDEA: Ctrl + Alt + B):

public abstract class AbstractExecutorService implements ExecutorService

然后就发现有两个类继承了这个虚拟类:

ThreadPoolExecutor 

public class ThreadPoolExecutor extends AbstractExecutorService

 ScheduledThreadPoolExecutor

public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService

这就是线程池不允许使用 Executor去创建的原因,可以通过 ThreadPoolExecutor 的方式,这样的处理方式也能更加明确线程池的运行规则,规避资源耗尽的风险。

通过ThreadPoolExecutor类创建,最原始的创建线程池的方式,它包含了 7 个参数可供设置,可以查看源码:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

corePoolSize 核心线程数

maximumPoolSize 最大线程数

keepAliveTime 线程存活时间

unit 时间单位

workQueue 等待队列

这是其中的一个构造函数,如果有其他的要求可以看其他的构造函数。


另一种方式是使用Executors,这是一个类:

public class Executors

可以看下面的函数,有很多创建各种各样类型线程池的函数,返回值都是ExecutorService:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。


 自己写了个例子,使用第一种方式:

public class ThreadPoolTest {

    public static void main(String[] args) {

        List<String> types = new ArrayList<>();
        for(int i = 0; i < 18; i++) {
            types.add("Test" + i);
        }

        ExecutorService executorService = new ThreadPoolExecutor(4, 6, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(12));

        for(String type : types) {
            ThreadAssembler threadAssembler = new ThreadAssembler();
            threadAssembler.setType(type);
            executorService.execute(threadAssembler);
        }

    }
}

这里List的长度是18,所以在创建线程池的时候,maximumPoolSize + workQueue.size() >= 18,不然会报错(毕竟等待的线程塞不进你申请的线程池)。

public class AllAssembler {

    protected String type;

    public void setType(String type) {
        this.type = type;
    }
}
public class ThreadAssembler extends AllAssembler implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("Get Thread Assember " + type);
        } catch (Exception e) {
            System.out.println("Error");
        }
   

最后的结果:

posted @ 2022-04-18 22:36  疏影龙栖  阅读(47)  评论(0)    收藏  举报