一、JDK底层给我们提供了哪些常用的创建线程池的方法?

JDK主要是通过Executors工具类来创建线程池方法

1.newFixedThreadPool(int Thread) 创建固定线程数的线程池

底层实现:

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

2.newCacheThreadPool() 创建可缓存的线程池,如果线程池中有可用的线程则复用,没有的话就一直创建线程

底层实现:

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());
    }

3.newSingleThreadPool() 创建一个单线程的线程池

底层实现:

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

4.newScheduledThreadPool(int corePoolSize) 创建一个支持定时及周期性的任务执行的线程池,可代替用Timer定时器类

底层实现:

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue());
    }

二、为什么在开发的时候不建议使用这几种线程池创建?

1.newFixedThreadPool和newSingleThreadPool在底层的实现上面用的阻塞队列是LinkedBlockingQueue实现的,在未指定初始化的大小时,默认是Integer.MAX_VALUE,大约是2的31次方,导致允许的队列太长,请求大量的堆积,从而导致OOM

2.newCacheThread和newScheduleThreadPool允许创建的最大线程数量为Integer.MAX_VALUE,可能导致无限的创建线程,导致资源耗尽,从而OOM.

三、阻塞队列的种类和选择?

1.ArrayBlockingQueue 有界队列

内部是用数组存储元素的,底层是通过ReentrantLock实现的线程安全,在创建它的时候需要指定容量,之后也不可以在扩容,在构造函数中我们可以指定是否公平:ArrayBlockingQueue(int capacity, boolean fair)

第一个参数是容量,第二个参数是否公平。如果设置非公平那么就有可能存在插队的可能,设置公平的话,按FIFO的方式获取线程资源,其他的线程不允许插队。

2.LinkedBlockindQueue 有界对列

内部是用链表实现的,如果我们不指定大小,默认是Integer.MAX_VALUE,由于是非常大,这种场景下可以作为无界队列使用。

3.SynchronusQueue 相当于有界队列

内部的容量是0, SynchronousQueue 不需要去持有元素,它所做的就是直接传递(direct handoff)。由于每当需要传递的时候,SynchronousQueue 会把元素直接从生产者传给消费者,在此期间并不需要做存储,所以如果运用得当,它的效率是很高的

4.PriorityBlockingQueue 无界队列

ArrayBlockingQueue 和 LinkedBlockingQueue 都是采用先进先出的顺序进行排序,可是如果有的时候我们需要自定义排序怎么办呢?这时就需要使用 PriorityBlockingQueue无界队列,而且会自动扩容.

PriorityBlockingQueue 是一个支持优先级的无界阻塞队列,可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。

5.DelayQueue 无界队列

DelayQueue这个队列具有延迟的功能,我们可以设定队列中的任务延迟多久之后执行,例如10s后执行,或者30分钟后未付款自动取消订单等需要延迟执行的场景中大量使用,它是无界队列,放入的元素必须实现 Delayed 接口,而 Delayed 接口又继承了 Comparable 接口,所以自然就拥有了比较和排序的能力,代码如下

public interface Delayed extends Comparable {
    long getDelay(TimeUnit unit);
}

可以看出这个 Delayed 接口继承自 Comparable,里面有一个需要实现的方法,就是 getDelay。这里的 getDelay 方法返回的是“还剩下多长的延迟时间才会被执行”,如果返回 0 或者负数则代表任务已过期

元素会根据延迟时间的长短被放到队列的不同位置,越靠近队列头代表越早过期。

DelayQueue 内部使用了 PriorityQueue 的能力来进行排序

限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注