Java线程池

    网上关于线程池的文章比比皆是,自己再写,只为了加深印象。也是对自己学过的东西做一下简单的总结。


引子


    在Android里面写的线程池,弹出这样的提示,说明有更好的写法。

阿里的 Java开发手册,上面有线程池的一个建议:
    线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

    

Executors 各个方法的弊端:
1)newFixedThreadPool 和 newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。
2)newCachedThreadPool 和 newScheduledThreadPool:
主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。

ThreadPoolExecutor
先看看如何使用ThreadPoolExecutor创建线程池:
public ThreadPoolExecutor ( int corePoolSize,
                              int maximumPoolSize,
                             long keepAliveTime,
                              TimeUnit unit,                               BlockingQueue<Runnable> workQueue,                               ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
corePoolSize - 线程池核心池的大小。
maximumPoolSize - 线程池的最大线程数。
keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
unit - keepAliveTime 的时间单位。
workQueue - 用来储存等待执行任务的队列。
threadFactory - 线程工厂。
handler - 拒绝策略。

Executors工厂方法:

让我们再看看Executors提供的那几个工厂方法。
newSingleThreadExecutor
创建一个单线程的线程池 。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。
此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
 public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
newFixedThreadPool
创建固定大小的线程池。 每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。
线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
newCachedThreadPool
创建一个可缓存的线程池 。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。
此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    这么看来,其实ExecutorService exec1 = Executors.newSingleThreadExecutor();
已经是 是通过 ThreadPoolExecutor 的方式创建,不过正如最上面的图片中显示的,建议手动创建。那么我们就手动创建一个:

 /**
     * 生成一个无界的并使用缓存的ThreadPoolExecutor
     */
    public static ExecutorService newCachedThreadPool() {
        ThreadFactory factoryName = new PriorityThreadFactory("thread-tcp", android.os.Process.THREAD_PRIORITY_BACKGROUND);

        return new ThreadPoolExecutor(2, Integer.MAX_VALUE,

                60L, TimeUnit.SECONDS,

                new SynchronousQueue<Runnable>(),factoryName);

    }
红色部分是自定义线程名字,Java中也可以利用org.apache.commons.lang3写成:
ThreadFactory tf = new BasicThreadFactory.Builder().namingPattern("自定义").daemon(true).build();

    至此,完成。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值