线程池 的创建小列子,以及参数的介绍

线程池的概念大家应该都很清楚,帮我们重复管理线程,避免创建大量的线程增加开销。

除了降低开销以外,线程池也可以提高响应速度,了解点 JVM 的同学可能知道,一个对象的创建大概需要经过以下几步:

  1. 检查对应的类是否已经被加载、解析和初始化
  2. 类加载后,为新生对象分配内存
  3. 将分配到的内存空间初始为 0
  4. 对对象进行关键信息的设置,比如对象的哈希码等
  5. 然后执行 init 方法初始化对象

创建一个对象的开销需要经过这么多步,也是需要时间的嘛,那可以复用已经创建好的线程的线程池,自然也在提高响应速度上做了贡献。

public class ThreadPool {

//创建自己的线程池

    //一、.先定义线程池的几个关键属性值
    private static final int CORE_POOL_SIZE =  Runtime.getRuntime().availableProcessors();//核心线程数是cpu数的两倍
    private static final int MAXIMUM_POOL_SIZE = 64;//线程池最大的线程数
    private static final long KEEP_ALIVE_TIME = 1;  //空闲线程保持存活时间为1秒

    //二、.然后根据处理的任务类型选择不同的阻塞队列

   /* 线程池中使用的队列是 BlockingQueue 接口,常用的实现有如下几种:

   1. ArrayBlockingQueue:基于数组、有界,按 FIFO(先进先出)原则对元素进行排序
    2. LinkedBlockingQueue:基于链表,按FIFO (先进先出) 排序元素
         吞吐量通常要高于 ArrayBlockingQueue
         Executors.newFixedThreadPool() 使用了这个队列
    3. SynchronousQueue:不存储元素的阻塞队列
           每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态
           吞吐量通常要高于 LinkedBlockingQueue
           Executors.newCachedThreadPool使用了这个队列
    4.PriorityBlockingQueue:具有优先级的、无限阻塞队列*/
    private final BlockingQueue<Runnable> mWorkQueue = new LinkedBlockingQueue<>(128);

    //三、创建自己的ThreadFactory
    //在其中为每个线程设置个名称
    //获取本类的类名简称Class.getName():以String的形式,返回Class对象的“实体”名称;
    //Class.getSimpleName():获取源代码中给出的“底层类”简称。
    private final String TAG = this.getClass().getSimpleName();
    private final ThreadFactory DEFAULT_THREAD_FACTORY =  new ThreadFactory() {
        //AtomicInteger提供原子操作来进行Integer的使用,因此十分适合高并发情况下的使用。AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。
        private final AtomicInteger mCount = new AtomicInteger(1);
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r,TAG + "#" +mCount.getAndIncrement());
            thread.setPriority(Thread.NORM_PRIORITY);//设置线程的优先级别,值越小,级别越高,这种不是绝对的,只是几率大。
            return thread;
        }
    };
    //四、然后创建线程池

    private ThreadPoolExecutor mExecutor = new ThreadPoolExecutor(
                                                CORE_POOL_SIZE,//核心线程的数量
                                                MAXIMUM_POOL_SIZE, //最大线程数量
                                                KEEP_ALIVE_TIME,//超出核心线程数量以外的线程空余存活时间
                                                TimeUnit.SECONDS,//存活时间的单位
                                                mWorkQueue,//保存待执行任务的队列
                                                DEFAULT_THREAD_FACTORY,//创建新线程使用的工厂
                                                new ThreadPoolExecutor.DiscardOldestPolicy() // 当任务无法执行时的处理器
            );

   private static volatile ThreadPool mInstance = new ThreadPool();

   public static ThreadPool getInstance(){
       return mInstance;
    }

    public void addTask(Runnable runnable){
       mExecutor.execute(runnable);//提交任务的方法  还有一个就是 mExecutor.submit(),提交需要返回值的任务,

         //submit() 有三种重载,参数可以是 Callable 也可以是 Runnable

           //同时它会返回一个 Funture 对象,通过它我们可以判断任务是否执行成功。

           //获得执行结果调用 Future.get() 方法,这个方法会阻塞当前线程直到任务完成}

//线程池即使不执行任务也会占用一些资源,所以在我们要退出任务时最好关闭线程池。
    //有两个方法关闭线程池
    // 1.将线程池设置为 STOP,然后尝试停止所有线程,并返回等待执行任务的列表
    @Deprecated
    public void shutDownNow(){
       mExecutor.shutdownNow();
    }
    //2.将线程池的状态设置为 SHUTDOWN,然后中断所有没有正在执行的线程

    //它们的共同点是:都是通过遍历线程池中的工作线程,逐个调用 Thread.interrup() 来中断线程,所以一些无法响应中断的任务可能永远无法停止(比如 Runnable)。
    @Deprecated
    public void shutDown(){
       mExecutor.shutdown();
    }


}

 想更深了解线程池,请点击这个链接

:https://blog.csdn.net/mine_song/article/details/70948223

原文地址:https://www.cnblogs.com/laosunlaiye/p/9246657.html