天天看点

线程池有这一篇就够了

1.线程池ThreadPoolExecutor

线程池主要就是Executor接口,这个接口提供一些对于线程的操作的配置和方法,能对线程的性能带来较大提升。

线程池得好处:

(1)降低了线程的创建和销毁的时间消耗,能够提升线程对系统资源的利用率,同时线程执行完后并不是直接销毁,而是回到线程池等待执行其他任务,这样提高了线程的复用率。

(2)对线程时可控的。相比于传统的多线程每个任务分配一个线程来说,线程池可以通过配置来完成对线程的延时或定时执行。

(3)可避免由于过多线程对共享资源的争抢而造成线程阻塞。线程池中提供了newFixedThreadPool()方法可以设定线程的个数,这样就能降低过多的线程对资源争抢而造成线程阻塞的问题的发生。

线程池得配置参数:

(1)int CorePoolSize:

指的是线程池中核心线程的个数,核心线程指的是:当在线程池中创建线程执行任务时,如果线程池中线程的个数小于CorePoolSize则创建的线程就是核心线程,超过CorePoolSize时就是非核心线程。

核心线程在线程池中无论是否在执行任务还是处于闲置状态,都不会被销毁。当然可以手动读线程池中闲置的核心线程进行销毁,即把allowCoreThreadTimeOut=true,设为true就可以让闲置的核心线程销毁。

(2)int maximumSize:

Maxmumsize指的是线程池中所有线程加起来最大的线程数,如果超过这个线程数将会报出异常。MaximumSize=CorePoolSize(核心线程数)+非CorePoolSize(非核心线程数)。当线程池的线程需要从人物队列中获取任务时就会在线城池中创建一个线程,如果线程数没有超过CorePoolSize则创建的是核心线程,如果超过了就会创建非核心线程。当线程数超过maximumSize时会报出异常。

(3)long keepAliveTime:

keepAliveTime指的是非核心线程闲置最大超时时间,超过指定的keepAliveTime时线程就会被销毁。如果设置allowCoreThreadTimeOut=true那么就是指的是核心线程的闲置的最大超时时长。

(4)TimeUnit unit:

keepAliveTime的时间单位,是一个枚举类型,主要包括:

· NANOSECONDS : 1微毫秒 = 1微秒 / 1000

· MICROSECONDS : 1微秒 = 1毫秒 / 1000

· MILLISECONDS : 1毫秒 = 1秒 /1000

· SECONDS : 秒

· MINUTES : 分

· HOURS : 小时

· DAYS : 天

(5)BlockingQueue WorkQueue(任务阻塞队列)

任务队列,线程池中线程需要执行的任务都在这里存放获取。当线程执行任务时会现在线程池中创建一个线程(核心线程),如果核心线程都在执行任务时,核心线程没有闲置的,那么任务就会存放在任务队列中,当任务队列任务存满了发生阻塞时,会则会在线程池中创建非核心线程执行任务。
           

任务队列有四种类型:

1)synchronizesQueue:同步队列,这个队列一旦接受到任务会立即把任务交给线程池中的线程进行执行。但如果线程池中的线程没有闲置的那么就会创建一个线程,为了保证同步队列的任务能马上被线程执行,所以设置线程池得最大线程数maximumSize为无限大。

2)LinkedBlockingQueue:链表阻塞队列。当线程需要执行这个队列的任务时,如果线程池中的线程数小于CorePoolSize那么会创建核心线程执行队列任务,如果超过CorePoolSize时则任务会被放在LinkedBlockingQueue中,等待核心线程执行完。这样就导致了非核心线程永远不会创建执行LinkedBlockingQueue中的任务,那么maximumSize永远小于CorePoolSize的数。

3)ArrayBlockingQueue:数组阻塞队列。可以规定队列的长度,在接受到任务时会现在线程池中创建核心线程,如果核心线程数达到了指定的CorePoolSize那么任务进入ArrayBlockingQueue队列中等待,如果队列满了,那么在线程池中创建非核心线程,如果线程池中的线程数达到了指定的maximumSize,那么最会线程抛出异常。

4)DelayQueue:延时队列。执行任务时必须要实现Delay接口。在该队列的任务执行符合队列规则,先进入的任务先被执行,后进入的任务后被执行。同时执行需要延时一定时间后才能被执行。

怎样想线程池中提交一个任务:

向线程翅中提交一个任务,可以使用ThreadPoolExecutor的一个方法:ThreadPoolExecutor.execute(Runnable)。

ThreadPoolExecutor的执行策略:

(1)线程池从队列中接受到一个任务时,会首先创建一个核心线程执行任务。

(2)核心线程数达到指定的CorePoolSize的值,任务就会存放在队列中。

(3)当队列中惹任务存满了队列时,则会在线程池中创建非核心线程,继续执行队列中的任务。

(4)当线程池中的总的线程数达到指定的maximumSize时并且队列中任务也存满了,那么就会由RejectedExecutionHandler抛出异常。

常见的四种线程池:

(1)newFixedThreadPool:定长线程池。

该线程池可以指定线程的个数,每提交一个任务时就会创建一个线程,如果线程数达到newFixedThreadPool那么线程池不在创建线程,未执行的任务放在队列中等待。

优点是可以控制线程的最大并发数,避免创建很多线程时争抢共享资源造成的线程阻塞问题。

创建该线程的方式:

ExecutorService pool=Executors.newFixedThreadPool(int nThread);

(2)newCachedThreadPool:缓存线程池。

在newCachedThreadPool线程池中创建的线程数是不限制的,如果任务数小于线程数时,闲置的线程会被回收。

优点:可以对线程池中的线程进行复用,避免了因线程不断被创建和销毁的资源浪费问题,提高了线程的执行效率。线程池中有闲置的线程则利用闲置线程执行任务,没有则创建线程,如果线程数小于任务数那么闲置线程会被回收。

创建该线程的方式:

ExecutorService pool=Executors.newCachedThreadPool();

(3)newSingleThreadPool:单线程线程池

在线程池中只有一个线程被执行,如果该线程异常结束,则会创建另一个线程来执行。完全准守队列的执行顺序,先请求的任务先被执行。

创建方法:

ExecutorService pool=Executors.newSingleThreadPool();

(4)newScheduledThreadPool:定时线程池

NewScheduledThreadPool会固定线程数,并且可以定时或者延时执行任务。

创建方法:

ExecutorService pool=Executors.newScheduledThreadPool(int CorePoolSize);

继续阅读