1. 线程池的介绍:

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。

2. 线程池的优点:

  1. 不用频繁的new新对象,节省系统性能开销。
  2. 可控制线程数量,避免过度新建线程无法销毁造成资源浪费,严重的直接宕机。

3. 应用场景:

  1. 需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
  2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,并出现"OutOfMemory"的错误。

4. 示例:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolUtil {
	private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 20, 20, 
			TimeUnit.MILLISECONDS, (BlockingQueue)new LinkedBlockingQueue<>());
	public static ThreadPoolExecutor getThreadPoolExecutor() {
		return threadPoolExecutor;
	}
}

java 线程池异常没有打印 java线程池threadpool_java 线程池异常没有打印


新建一个单利线程池工具类,ThreadPoolExecutor有多个构造方法,当前使用的第一个。其中参数的意义如下:

序号

名称

类型

含义

1

corePoolSize

int

核心线程池大小

2

maximumPoolSize

int

最大线程池大小

3

keepAliveTime

long

线程最大空闲时间

4

unit

TimeUnit

时间单位

5

workQueue

BlockingQueue

线程等待队列

6

threadFactory

ThreadFactory

线程创建工厂

7

handler

RejectedExecutionHandler

拒绝策略

corePoolSize:指定了线程池中的线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去;当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。

maximumPoolSize:指定了线程池中的最大线程数量,这个参数会根据你使用的workQueue任务队列的类型,决定线程池会开辟的最大线程数量;如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。值得注意的是,如果使用了无界的任务队列这个参数就没用了

keepAliveTime:当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁;

unit:keepAliveTime的单位,可选的单位有天(Days)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)

workQueue:任务队列,被添加到线程池中,但尚未被执行的任务;它一般分为直接提交队列、有界任务队列、无界任务队列、优先任务队列几种;
(1)ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,FIFO(先进先出)。
(2)LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue,静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
(3)SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool()使用了这个队列。
(4)PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

threadFactory:线程工厂,用于创建线程,可以通过线程工厂给每个创建出来的线程设置更有意义的名字一般用默认即可;

handler:拒绝策略;当任务太多来不及处理时,如何拒绝任务;
(1)AbortPolicy:直接抛出异常,默认情况下采用这种策略
(2)CallerRunsPolicy:只用调用者所在线程来运行任务
(3)DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务
(4)DiscardPolicy:不处理,丢弃掉

5. 调用:

在需要使用线程处理的地方调用线程池工具类:

ThreadPoolUtil.getThreadPoolExecutor().execute(new SaveNotifyThread(info, 1, user.getId(), "orderNum="+order.getOrderNum()));

SaveNotifyThread是一个继承Thread或者实现Runnable接口的自定义类。