通过SingleThreadExecutor源码窥探面向对象设计模式

本文探讨了Java中的SingleThreadExecutor如何通过封装防止核心线程池大小和最大线程池大小在运行时被修改。对比FixedThreadPool,SingleThreadExecutor使用FinalizableDelegatedExecutorService进行封装,避免了直接暴露ThreadPoolExecutor导致的参数可变风险。设计中体现了封装和多态性原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文4300+字,实际文字大概300,建议阅读时间10分钟

我们知道Java预留了四种多线程池

其中一种为SingleThreadExecutor,如同其字面意思就是单线程池,看一下源码:
源码来自Executors类中静态方法

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

为了体现设计模式,我们再给出另一个线程池FixedThreadPool的源码

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

发现所有的预留多线程池只不过就是对不同参数的饿ThreadPoolExecutor的处理,值得提一下,如果你对ThreadPoolExecutor不熟悉的话,我贴出源码

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
     

省略构造方法体内容,只介绍两个参数:
corePoolSize 核心线程池大小
maximumPoolSize 最大线程池大小

我们希望刚才的newSingleThreadExecutor是单线程,其中corePoolSize = maximumPoolSize = 1 。

问题来了:如何设计保证线程池在运行中 corePoolSize和maximumPoolSize不变?

如果像FixedThreadPool那样设计会带来一个什么风险?

即直接返回一个ThreadPoolExecutor对象,用Service接口类接收的方式

如下图的继承关系可以直接通过强制类型转换,把ThreadPoolExecutor强制转换为ThreadPoolExecutor对象,通过set方法改变该值。
ThreadPoolExecutor的层次关系
在这里插入图片描述

封装一个新的类FinalizableDelegatedExecutorService

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

给出FinalizableDelegatedExecutorService源码:

static class FinalizableDelegatedExecutorService
        extends DelegatedExecutorService {
        FinalizableDelegatedExecutorService(ExecutorService executor) {
            super(executor);
        }
        protected void finalize() {
            super.shutdown();
        }
    }

可以看出该内部类继承于DelegatedExecutorService,那么继续给出DelegatedExecutorService源码

static class DelegatedExecutorService extends AbstractExecutorService {
        private final ExecutorService e;
        DelegatedExecutorService(ExecutorService executor) { e = executor; }
        public void execute(Runnable command) { e.execute(command); }
        public void shutdown() { e.shutdown(); }
        public List<Runnable> shutdownNow() { return e.shutdownNow(); }
        public boolean isShutdown() { return e.isShutdown(); }
        public boolean isTerminated() { return e.isTerminated(); }
        public boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException {
            return e.awaitTermination(timeout, unit);
        }
        public Future<?> submit(Runnable task) {
            return e.submit(task);
        }
        public <T> Future<T> submit(Callable<T> task) {
            return e.submit(task);
        }
        public <T> Future<T> submit(Runnable task, T result) {
            return e.submit(task, result);
        }
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException {
            return e.invokeAll(tasks);
        }
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                             long timeout, TimeUnit unit)
            throws InterruptedException {
            return e.invokeAll(tasks, timeout, unit);
        }
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException {
            return e.invokeAny(tasks);
        }
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                               long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException {
            return e.invokeAny(tasks, timeout, unit);
        }
    }

不要被这种代码吓到,看构造器:

DelegatedExecutorService(ExecutorService executor) { e = executor; }

把子类ThreadPoolExecutor隐式转为父类对象ExecutorService,在封装给成员变量e, 其中所有方法通过e来调用.并把e 私有,取消private方法,且DelegatedExecutorService和ThreadPoolExecutor无继承关系,仅都实现了接口ExecutorService,这样就消除了强制类型转换的可能。彻底的把ThreadPoolExecutor隐藏起来,这就是封装的体现
在这里插入图片描述

这种方法实现的原理

把SingleThreadExecutor(ThreadPoolExecutor的对象)封装在了一个FinalizableDelegatedExecutorService对象中,FinalizableDelegatedExecutorService父类DelegatedExecutorService包含有一个ExecutorService(接口)e对象, 而其本身也是ExecutorService(接口)对象,并且其实现了部分ThreadPoolExecutor功能(调用e对象),此外,去掉了set 和get 把e隐藏,无法改变e

这种方法既然不是相同子类,如何对上层无痛(没有感觉)?

都实现了ExecutorService接口,此外所有多线程池的返回都是ExecutorService接口对象。
多态性的体现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值