Java中的线程池(3)----SingleThreadExecutor

来源:互联网 发布:企业汉字做域名的品牌 编辑:程序博客网 时间:2024/05/21 10:31

本文简单介绍Java中的另一种线程池----SingleThreadExecutor。

创建SingleThreadExecutor的静态方法

首先还是先看一下创建SingleThreadExecutor的Executors下的静态方法:

    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();        }    }
可以看到FinalizableDelegatedExecutorService这个类实际上继承了DelegatedExecutorService,然后加了个finalize方法保证线程池的关闭。那么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);        }    }
实际上就是对ExecutorService类进行了一个包装,相当于设计模式中的装饰者模式,防止暴露出一些不应该暴露的方法。


说到这里应该很明了了,实际上FinalizableDelegatedExecutorService这个类就是对ExecutorService进行了一个包装,防止暴露出不该被暴露的方法,然后加上了finalize方法保证线程池的关闭。

现在回头看newSingleThreadExecutor这个静态方法,根据其调用的ExecutorService构造函数的构造参数,可以了解到:

1、这种线程池的核心线程池大小为1,线程池最多线程数量也为1,因此keepAliveTime实际上也就没有意义了;

2、这种线程池的阻塞队列为LinkedBlockingQueue<Runnable>类型的,LinkedBlockingQueue在上一篇文章说过了,是一种最大容量为Integer.MAX_VALUE的,放入锁和取出锁不一样的一种阻塞队列。


那么问题来了,newSingleThreadExecutor()和newFixedThreadPool(1)有什么区别呢?

上面说了那么多,答案应该也很显而易见了,实际上差别仅仅在于newSingleThreadExecutor()返回的线程池少暴露了一些方法并且多了个finalize方法保证线程池调用shutdown(),仅此而已

网上有一些错误的回答,比如说前者线程执行期间抛出异常仍然能保证又其他线程顶替他,而后者不行,这样的回答都是错的。想要论证这是错的实际上很简单,对newFixedThreadPool(1)进行测试:

package newFixedThreadPool;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Test {    public static void main(String[] args) {        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);        int i = 0;        while (i++<10) {            final int index = i;            fixedThreadPool.execute(new Runnable() {                @Override                public void run() {                    if(index == 1){                        throw new IllegalStateException("handler exception");//线程运行时抛出异常                    }                    System.out.println(Thread.currentThread().getName() + "执行");                    try {                        Thread.sleep(3000);//模拟当前线程执行其他操作 花费3s                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            });        }        fixedThreadPool.shutdown();    }}
运行结果如下:


可以看到对于newFixedThreadPool(1),当一个线程在运行时抛出异常也会有其他线程顶替他去完成接下来的任务。

接下来对newSingleThreadExecutor()方法进行测试:

package newSingleThreadExecutor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Test {    public static void main(String[] args) {        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();        int i = 0;        while (i++ < 10) {            final int index = i;            singleThreadExecutor.execute(new Runnable() {                @Override                public void run() {                    if(index == 1){                        throw new IllegalStateException("handler exception");                    }                    System.out.println(Thread.currentThread().getName() + "执行" + "No." + index);                }            });        }        singleThreadExecutor.shutdown();    }}


执行结果如下:


对于newSingleThreadExecutor()来说,也是当线程运行时抛出异常的时候会有新的线程加入线程池替他完成接下来的任务。


以上为自己的一些认识 如果有错误请指出

原创粉丝点击