一、JAVA线程池使用
在使用Java多线程时引入线程池技术可以大大提高程序性能。Java提供的线程池相关的类主要有四个:Executor、ExecutorService、ScheduledExecutorService和ThreadPoolExecutor。其中,使用ThreadPoolExecutor类可以对线程池进行灵活的设置,可以很好地适应各种场景。
二、JAVA线程池参数设置
在使用Java线程池时,可以根据实际情况对线程池进行参数设置,以达到最佳的程序性能。线程池的主要参数包括以下几个方面:
1、corePoolSize
核心池大小,即线程池初始化后启动的线程数量。如果当前线程数量小于核心池大小,则新建线程;否则会将任务放入任务队列等待执行。
2、maximumPoolSize
最大线程数量,即线程池中最多同时执行的线程数量。当线程池中已有的线程数大于等于corePoolSize时,新任务到来时会将任务放入任务队列中等待。当任务到来时任务队列已满且当前线程数小于maximumPoolSize,则新建线程执行该任务。当线程数已达到最大线程数且任务队列已满,则会根据所设置的RejectedExecutionHandler进行相应的拒绝处理。
3、keepAliveTime
线程空闲时间,即空闲线程的存活时间。当线程池中线程数量大于corePoolSize时,需要有一定的机制来回收空闲线程,以便于释放系统资源。当空闲时间超过keepAliveTime时,空闲线程将被回收。
4、TimeUnit
空闲时间的时间单位。该项参数以TimeUnit枚举类型传入,可以设置为TimeUnit.SECONDS、TimeUnit.MINUTES、TimeUnit.HOURS等。
5、workQueue
任务队列。当线程池中线程数量达到corePoolSize时,新任务到来会被放入任务队列中。该任务队列可以是SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue等各种线程安全队列,也可以根据需要自己实现。
6、threadFactory
线程工厂。用于创建新的线程对象。可以通过ThreadFactoryBuilder来创建一个线程工厂。
7、rejectedExecutionHandler
任务拒绝策略。当线程池中线程数量已达到maximumPoolSize并且任务队列已经满了时,需要有一种机制来处理新到达的任务。主要有四种处理方式:
- AbortPolicy(默认):直接抛出RejectedExecutionException异常。
- CallerRunsPolicy:任务由调用线程直接执行。
- DiscardOldestPolicy:将等待时间最长的任务从队列中移除,将新任务加入队列中。
- DiscardPolicy:直接丢弃该任务。
三、JAVA创建线程池
Java提供了四个线程池类,分别是:
- FixedThreadPool
- CachedThreadPool
- SingleThreadExecutor
- ScheduledThreadPool
1、FixedThreadPool
FixedThreadPool固定大小线程池,会一直新建线程直到线程达到线程池的最大大小,线程池中的线程都是活跃的,线程池中线程数量不会超过给定的数量,并且线程都是在空闲状态下等待接收任务,所以线程利用率高。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()); }
2、CachedThreadPool
CachedThreadPool线程池的大小会根据执行的任务数量自动扩展和收缩,没有核心线程数,超过60秒空闲的线程被终止并从缓冲池中删除。适用于执行大量短期异步任务的情景。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue()); }
3、SingleThreadExecutor
SingleThreadExecutor单线程池中只有一个核心线程,该线程会按先进先出的方式执行任务,所以不需要考虑线程同步的问题。适用于需要排队依次执行任务的情况。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue())); }
4、ScheduledThreadPool
ScheduledThreadPool定长线程池可以定时或周期性地执行任务。适用于需要执行定时任务的情况。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
完整的Java线程池使用实例:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class ThreadPoolTest { public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(() -> { System.out.println("任务1开始执行"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务1执行完毕"); }); executorService.execute(() -> { System.out.println("任务2开始执行"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务2执行完毕"); }); executorService.execute(() -> { System.out.println("任务3开始执行"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("任务3执行完毕"); }); executorService.shutdown(); executorService.awaitTermination(1, TimeUnit.HOURS); } }