java线程池中Worker线程执行流程原理解析

目录
  • 引言
    • Worker类分析
    • runWorker(Worker)方法
    • getTask()方法
    • beforeExecute(Thread, Runnable)方法
    • afterExecute(Runnable, Throwable)方法
    • processWorkerExit(Worker, boolean)方法
    • tryTerminate()方法
    • terminated()方法

引言

在《【高并发】别闹了,这样理解线程池执行任务的核心流程才正确!!》一文中我们深度分析了线程池执行任务的核心流程,在ThreadPoolExecutor类的addWorker(Runnable, boolean)方法中,使用CAS安全的更新线程的数量之后,接下来就是创建新的Worker线程执行任务,所以,我们先来分析下Worker类的源码。

Worker类分析

Worker类从类的结构上来看,继承了AQS(AbstractQueuedSynchronizer类)并实现了Runnable接口。本质上,Worker类既是一个同步组件,也是一个执行任务的线程。

接下来,我们看下Worker类的源码,如下所示。

private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
	private static final long serialVersionUID = 6138294804551838833L;
	//执行任务的线程类
	final Thread thread;
	//初始化执行的任务,第一次执行的任务
	Runnable firstTask;
	//完成任务的计数
	volatile long completedTasks;
	//Worker类的构造方法,初始化任务并调用线程工厂创建执行任务的线程
	Worker(Runnable firstTask) {
		setState(-1);
		this.firstTask = firstTask;
		this.thread = getThreadFactory().newThread(this);
	}
	//重写Runnable接口的run()方法
	public void run() {
		//调用ThreadPoolExecutor类的runWorker(Worker)方法
		runWorker(this);
	}
	//检测是否是否获取到锁
	//state=0表示未获取到锁
	//state=1表示已获取到锁
	protected boolean isHeldExclusively() {
		return getState() != 0;
	}
	//使用AQS设置线程状态
	protected boolean tryAcquire(int unused) {
		if (compareAndSetState(0, 1)) {
			setExclusiveOwnerThread(Thread.currentThread());
			return true;
		}
		return false;
	}
	//尝试释放锁
	protected boolean tryRelease(int unused) {
		setExclusiveOwnerThread(null);
		setState(0);
		return true;
	}
	public void lock()        { acquire(1); }
	public boolean tryLock()  { return tryAcquire(1); }
	public void unlock()      { release(1); }
	public boolean isLocked() { return isHeldExclusively(); }
	void interruptIfStarted() {
		Thread t;
		if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
			try {
				t.interrupt();
			} catch (SecurityException ignore) {
			}
		}
	}
}

在Worker类的构造方法中,可以看出,首先将同步状态state设置为-1,设置为-1是为了防止runWorker方法运行之前被中断。这是因为如果其他线程调用线程池的shutdownNow()方法时,如果Worker类中的state状态的值大于0,则会中断线程,如果state状态的值为-1,则不会中断线程。

Worker类实现了Runnable接口,需要重写run方法,而Worker的run方法本质上调用的是ThreadPoolExecutor类的runWorker方法,在runWorker方法中,会首先调用unlock方法,该方法会将state置为0,所以这个时候调用shutDownNow方法就会中断当前线程,而这个时候已经进入了runWork方法,就不会在还没有执行runWorker方法的时候就中断线程。

注意:大家需要重点理解Worker类的实现。

Worker类中调用了ThreadPoolExecutor类的runWorker(Worker)方法。接下来,我们一起看下ThreadPoolExecutor类的runWorker(Worker)方法的实现。

runWorker(Worker)方法

首先,我们看下RunWorker(Worker)方法的源码,如下所示。

final void runWorker(Worker w) {
	Thread wt = Thread.currentThread();
	Runnable task = w.firstTask;
	w.firstTask = null;
	//释放锁,将state设置为0,允许中断任务的执行
	w.unlock();
	boolean completedAbruptly = true;
	try {
		//如果任务不为空,或者从任务队列中获取的任务不为空,则执行while循环
		while (task != null || (task = getTask()) != null) {
			//如果任务不为空,则获取Worker工作线程的独占锁
			w.lock();
			//如果线程已经停止,或者中断线程后线程终止并且没有成功中断线程
			//大家好好理解下这个逻辑
			if ((runStateAtLeast(ctl.get(), STOP) ||
				 (Thread.interrupted() &&
				  runStateAtLeast(ctl.get(), STOP))) &&
				!wt.isInterrupted())
				//中断线程
				wt.interrupt();
			try {
				//执行任务前执行的逻辑
				beforeExecute(wt, task);
				Throwable thrown = null;
				try {
					//调用Runable接口的run方法执行任务
					task.run();
				} catch (RuntimeException x) {
					thrown = x; throw x;
				} catch (Error x) {
					thrown = x; throw x;
				} catch (Throwable x) {
					thrown = x; throw new Error(x);
				} finally {
					//执行任务后执行的逻辑
					afterExecute(task, thrown);
				}
			} finally {
				//任务执行完成后,将其设置为空
				task = null;
				//完成的任务数量加1
				w.completedTasks++;
				//释放工作线程获得的锁
				w.unlock();
			}
		}
		completedAbruptly = false;
	} finally {
		//执行退出Worker线程的逻辑
		processWorkerExit(w, completedAbruptly);
	}
}

这里,我们拆解runWorker(Worker)方法。

(1)获取当前线程的句柄和工作线程中的任务,并将工作线程中的任务设置为空,执行unlock方法释放锁,将state状态设置为0,此时可以中断工作线程,代码如下所示。

Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
//释放锁,将state设置为0,允许中断任务的执行
w.unlock();

(2)在while循环中进行判断,如果任务不为空,或者从任务队列中获取的任务不为空,则执行while循环,否则,调用processWorkerExit(Worker, boolean)方法退出Worker工作线程。

while (task != null || (task = getTask()) != null)

(3)如果满足while的循环条件,首先获取工作线程内部的独占锁,并执行一系列的逻辑判断来检测是否需要中断当前线程的执行,代码如下所示。

//如果任务不为空,则获取Worker工作线程的独占锁
w.lock();
//如果线程已经停止,或者中断线程后线程终止并且没有成功中断线程
//大家好好理解下这个逻辑
if ((runStateAtLeast(ctl.get(), STOP) ||
	 (Thread.interrupted() &&
	  runStateAtLeast(ctl.get(), STOP))) &&
	!wt.isInterrupted())
	//中断线程
	wt.interrupt();

(4)调用执行任务前执行的逻辑,如下所示

//执行任务前执行的逻辑
beforeExecute(wt, task);

(5)调用Runable接口的run方法执行任务

//调用Runable接口的run方法执行任务
task.run();

(6)调用执行任务后执行的逻辑

//执行任务后执行的逻辑
afterExecute(task, thrown);

(7)将完成的任务设置为空,完成的任务数量加1并释放工作线程的锁。

//任务执行完成后,将其设置为空
task = null;
//完成的任务数量加1
w.completedTasks++;
//释放工作线程获得的锁
w.unlock();

(8)退出Worker线程的执行,如下所示

//执行退出Worker线程的逻辑
processWorkerExit(w, completedAbruptly);

从代码分析上可以看到,当从Worker线程中获取的任务为空时,会调用getTask()方法从任务队列中获取任务,接下来,我们看下getTask()方法的实现。

getTask()方法

我们先来看下getTask()方法的源代码,如下所示。

private Runnable getTask() {
	//轮询是否超时的标识
	boolean timedOut = false;
	//自旋for循环
	for (;;) {
		//获取ctl
		int c = ctl.get();
		//获取线程池的状态
		int rs = runStateOf(c);
		//检测任务队列是否在线程池停止或关闭的时候为空
		//也就是说任务队列是否在线程池未正常运行时为空
		if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
			//减少Worker线程的数量
			decrementWorkerCount();
			return null;
		}
		//获取线程池中线程的数量
		int wc = workerCountOf(c);
		//检测当前线程池中的线程数量是否大于corePoolSize的值或者是否正在等待执行任务
		boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
		//如果线程池中的线程数量大于corePoolSize
		//获取大于corePoolSize或者是否正在等待执行任务并且轮询超时
		//并且当前线程池中的线程数量大于1或者任务队列为空
		if ((wc > maximumPoolSize || (timed && timedOut))
			&& (wc > 1 || workQueue.isEmpty())) {
			//成功减少线程池中的工作线程数量
			if (compareAndDecrementWorkerCount(c))
				return null;
			continue;
		}
		try {
			//从任务队列中获取任务
			Runnable r = timed ?
				workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
				workQueue.take();
			//任务不为空直接返回任务
			if (r != null)
				return r;
			timedOut = true;
		} catch (InterruptedException retry) {
			timedOut = false;
		}
	}
}

getTask()方法的逻辑比较简单,大家看源码就可以了,我这里就不重复描述了。

接下来,我们看下在正式调用Runnable的run()方法前后,执行的beforeExecute方法和afterExecute方法。

beforeExecute(Thread, Runnable)方法

beforeExecute(Thread, Runnable)方法的源代码如下所示。

protected void beforeExecute(Thread t, Runnable r) { }

可以看到,beforeExecute(Thread, Runnable)方法的方法体为空,我们可以创建ThreadPoolExecutor的子类来重写beforeExecute(Thread, Runnable)方法,使得线程池正式执行任务之前,执行我们自己定义的业务逻辑。

afterExecute(Runnable, Throwable)方法

afterExecute(Runnable, Throwable)方法的源代码如下所示。

protected void afterExecute(Runnable r, Throwable t) { }

可以看到,afterExecute(Runnable, Throwable)方法的方法体同样为空,我们可以创建ThreadPoolExecutor的子类来重写afterExecute(Runnable, Throwable)方法,使得线程池在执行任务之后执行我们自己定义的业务逻辑。

接下来,就是退出工作线程的processWorkerExit(Worker, boolean)方法。

processWorkerExit(Worker, boolean)方法

processWorkerExit(Worker, boolean)方法的逻辑主要是执行退出Worker线程,并且对一些资源进行清理,源代码如下所示。

private void processWorkerExit(Worker w, boolean completedAbruptly) {
	//执行过程中出现了异常,突然中断
	if (completedAbruptly)
		//将工作线程的数量减1
		decrementWorkerCount();
	//获取全局锁
	final ReentrantLock mainLock = this.mainLock;
	mainLock.lock();
	try {
		//累加完成的任务数量
		completedTaskCount += w.completedTasks;
		//将完成的任务从workers集合中移除
		workers.remove(w);
	} finally {
		//释放锁
		mainLock.unlock();
	}
	//尝试终止工作线程的执行
	tryTerminate();
	//获取ctl
	int c = ctl.get();
	//判断当前线程池的状态是否小于STOP(RUNNING或者SHUTDOWN)
	if (runStateLessThan(c, STOP)) {
		//如果没有突然中断完成
		if (!completedAbruptly) {
			//如果allowCoreThreadTimeOut为true,为min赋值为0,否则赋值为corePoolSize
			int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
			//如果min为0并且工作队列不为空
			if (min == 0 && ! workQueue.isEmpty())
				//min的值设置为1
				min = 1;
			//如果线程池中的线程数量大于min的值
			if (workerCountOf(c) >= min)
				//返回,不再执行程序
				return;
		}
		//调用addWorker方法
		addWorker(null, false);
	}
}

接下来,我们拆解processWorkerExit(Worker, boolean)方法。

(1)执行过程中出现了异常,突然中断执行,则将工作线程数量减1,如下所示。

//执行过程中出现了异常,突然中断
if (completedAbruptly)
	//将工作线程的数量减1
	decrementWorkerCount();

(2)获取锁累加完成的任务数量,并将完成的任务从workers集合中移除,并释放,如下所示。

//获取全局锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
	//累加完成的任务数量
	completedTaskCount += w.completedTasks;
	//将完成的任务从workers集合中移除
	workers.remove(w);
} finally {
	//释放锁
	mainLock.unlock();
}

(3)尝试终止工作线程的执行

//尝试终止工作线程的执行
tryTerminate();

(4)处判断当前线程池中的线程个数是否小于核心线程数,如果是,需要新增一个线程保证有足够的线程可以执行任务队列中的任务或者提交的任务。

//获取ctl
int c = ctl.get();
//判断当前线程池的状态是否小于STOP(RUNNING或者SHUTDOWN)
if (runStateLessThan(c, STOP)) {
	//如果没有突然中断完成
	if (!completedAbruptly) {
		//如果allowCoreThreadTimeOut为true,为min赋值为0,否则赋值为corePoolSize
		int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
		//如果min为0并且工作队列不为空
		if (min == 0 && ! workQueue.isEmpty())
			//min的值设置为1
			min = 1;
		//如果线程池中的线程数量大于min的值
		if (workerCountOf(c) >= min)
			//返回,不再执行程序
			return;
	}
	//调用addWorker方法
	addWorker(null, false);
}

接下来,我们看下tryTerminate()方法。

tryTerminate()方法

tryTerminate()方法的源代码如下所示。

final void tryTerminate() {
	//自旋for循环
	for (;;) {
		//获取ctl
		int c = ctl.get();
		//如果线程池的状态为RUNNING
		//或者状态大于TIDYING
		//或者状态为SHUTDOWN并且任务队列为空
		//直接返回程序,不再执行后续逻辑
		if (isRunning(c) ||
			runStateAtLeast(c, TIDYING) ||
			(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
			return;
		//如果当前线程池中的线程数量不等于0
		if (workerCountOf(c) != 0) {
			//中断线程的执行
			interruptIdleWorkers(ONLY_ONE);
			return;
		}
		//获取线程池的全局锁
		final ReentrantLock mainLock = this.mainLock;
		mainLock.lock();
		try {
			//通过CAS将线程池的状态设置为TIDYING
			if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
				try {
					//调用terminated()方法
					terminated();
				} finally {
					//将线程池状态设置为TERMINATED
					ctl.set(ctlOf(TERMINATED, 0));
					//唤醒所有因为调用线程池的awaitTermination方法而被阻塞的线程
					termination.signalAll();
				}
				return;
			}
		} finally {
			//释放锁
			mainLock.unlock();
		}
	}
}

(1)获取ctl,根据情况设置线程池状态或者中断线程的执行,并返回。

//获取ctl
int c = ctl.get();
//如果线程池的状态为RUNNING
//或者状态大于TIDYING
//或者状态为SHUTDOWN并且任务队列为空
//直接返回程序,不再执行后续逻辑
if (isRunning(c) ||
	runStateAtLeast(c, TIDYING) ||
	(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
	return;
//如果当前线程池中的线程数量不等于0
if (workerCountOf(c) != 0) {
	//中断线程的执行
	interruptIdleWorkers(ONLY_ONE);
	return;
}

(2)获取全局锁,通过CAS设置线程池的状态,调用terminated()方法执行逻辑,最终将线程池的状态设置为TERMINATED,唤醒所有因为调用线程池的awaitTermination方法而被阻塞的线程,最终释放锁,如下所示。

//获取线程池的全局
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
	//通过CAS将线程池的状态设置为TIDYING
	if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
		try {
			//调用terminated()方法
			terminated();
		} finally {
			//将线程池状态设置为TERMINATED
			ctl.set(ctlOf(TERMINATED, 0));
			//唤醒所有因为调用线程池的awaitTermination方法而被阻塞的线程
			termination.signalAll();
		}
		return;
	}
} finally {
	//释放锁
	mainLock.unlock();
}

接下来,看下terminated()方法。

terminated()方法

terminated()方法的源代码如下所示。

protected void terminated() { }

可以看到,terminated()方法的方法体为空,我们可以创建ThreadPoolExecutor的子类来重写terminated()方法,值得Worker线程调用tryTerminate()方法时执行我们自己定义的terminated()方法的业务逻辑。

以上就是java线程池中Worker线程执行流程原理解析的详细内容,更多关于java线程池Worker线程执行的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java线程池队列LinkedBlockingDeque

    目录 正文 LinkedBlockingDeque LinkedBlockingDeque和LinkedBlockingQueue的区别 正文 public enum QueueTypeEnum { ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue"), LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue"), DELAY_QUEUE(3, "DelayQueue"),

  • java高并发ThreadPoolExecutor类解析线程池执行流程

    目录 摘要 核心逻辑概述 execute(Runnable)方法 addWorker(Runnable, boolean)方法 addWorkerFailed(Worker)方法 拒绝策略 摘要 ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态. 今天,我们通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程,小伙伴们最好是打开IDEA,按照冰河说的步骤,调试下Th

  • java线程池ThreadPoolExecutor的八种拒绝策略示例详解

    目录 池化设计思想 线程池触发拒绝策略的时机 JDK内置4种线程池拒绝策略 拒绝策略接口定义 AbortPolicy(中止策略) DiscardPolicy(丢弃策略) DiscardOldestPolicy(弃老策略) 第三方实现的拒绝策略 Dubbo 中的线程拒绝策略 Netty 中的线程池拒绝策略 ActiveMQ 中的线程池拒绝策略 PinPoint 中的线程池拒绝策略 谈到 Java 的线程池最熟悉的莫过于 ExecutorService 接口了,jdk1.5 新增的 java.uti

  • Java线程池队列LinkedTransferQueue示例详解

    目录 正文 LinkedTransferQueue 正文 public enum QueueTypeEnum { ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue"), LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue"), DELAY_QUEUE(3, "DelayQueue"), PRIORITY_BLOCKING_QUEUE(4, "PriorityB

  • java 线程池封装及拒绝策略示例详解

    目录 前文 线程池的封装实现 ThreadPoolExecutor 线程池拒绝策略 任务队列 前文 提到线程的使用以及线程间通信方式,通常情况下我们通过new Thread或者new Runnable创建线程,这种情况下,需要开发者手动管理线程的创建和回收,线程对象没有复用,大量的线程对象创建与销毁会引起频繁GC,那么事否有机制自动进行线程的创建,管理和回收呢?线程池可以实现该能力. 线程池的优点: 线程池中线程重用,避免线程创建和销毁带来的性能开销 能有效控制线程数量,避免大量线程抢占资源造成

  • java ThreadPoolExecutor线程池拒绝策略避坑

    目录 1.场景 2. 原因分析 3.总结 4.思考 1.场景 线程池使用DiscardOldestPolicy拒绝策略,阻塞队列使用ArrayBlockingQueue,发现在某些情形下对于得到的Future,调用get()方法当前线程会一直阻塞. 为了便于理解,将实际情景抽象为下面的代码: ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( 1, 1, 1, TimeUnit.SECONDS, new ArrayBlo

  • Java线程池队列PriorityBlockingQueue和SynchronousQueue详解

    目录 正文 PriorityBlockingQueue阻塞优先队列 SynchronousQueue 正文 public enum QueueTypeEnum { ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue"), LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue"), DELAY_QUEUE(3, "DelayQueue"), PRIORITY_BLOCKING

  • java线程池中Worker线程执行流程原理解析

    目录 引言 Worker类分析 runWorker(Worker)方法 getTask()方法 beforeExecute(Thread, Runnable)方法 afterExecute(Runnable, Throwable)方法 processWorkerExit(Worker, boolean)方法 tryTerminate()方法 terminated()方法 引言 在<[高并发]别闹了,这样理解线程池执行任务的核心流程才正确!!>一文中我们深度分析了线程池执行任务的核心流程,在Th

  • Android中的Coroutine协程原理解析

    前言 协程是一个并发方案.也是一种思想. 传统意义上的协程是单线程的,面对io密集型任务他的内存消耗更少,进而效率高.但是面对计算密集型的任务不如多线程并行运算效率高. 不同的语言对于协程都有不同的实现,甚至同一种语言对于不同平台的操作系统都有对应的实现. 我们kotlin语言的协程是 coroutines for jvm的实现方式.底层原理也是利用java 线程. 基础知识 生态架构 相关依赖库 dependencies { // Kotlin implementation "org.jetb

  • 线程池中execute与submit的区别说明

    目录 线程池execute与submit区别 execute submit 例1 例2 线程池submit和execute方法原理 线程池的作用 线程池的原理 线程池execute与submit区别 在使用线程池的时候,看到execute()与submit()方法.都可以使用线程池执行一个任务,但是两者有什么区别呢? execute void execute(Runnable command); submit <T> Future<T> submit(Callable<T&g

  • JAVA 自定义线程池的最大线程数设置方法

    一:CPU密集型: 定义:CPU密集型也是指计算密集型,大部分时间用来做计算逻辑判断等CPU动作的程序称为CPU密集型任务.该类型的任务需要进行大量的计算,主要消耗CPU资源.  这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数. 特点:    01:CPU 使用率较高(也就是经常计算一些复杂的运算,逻辑处理等情况)非常多的情况下使用    02:针对单台机

  • 线上dubbo线程池耗尽CyclicBarrier线程屏障异常解决记录

    目录 事件背景 问题定位 解决问题 文末结语 事件背景 系统相关使用人员反馈系统故障,日志显示从ams系统服务提示dubbo处理线程不足,具体异常信息如下: 问题定位 从上图可知,dubbo的处理线程池满了,默认200个线程,活动线程也是200个.这个现象非常不正常,我们的应用并发还没有到这个程度能同时占用200个线程处理请求.然后去读了下dubbo源码,发现dubbo也认为这种情况不正常,然后帮我们记录了应用的线程堆栈信息,这个非常赞.代码如下: 上面这段代码,在线程池不够用时,会每隔十分钟输

  • Java线程池中多余的线程是如何回收的

    最近阅读了JDK线程池ThreadPoolExecutor的源码,对线程池执行任务的流程有了大体了解,实际上这个流程也十分通俗易懂,就不再赘述了,别人写的比我好多了. 不过,我倒是对线程池是如何回收工作线程比较感兴趣,所以简单分析了一下,加深对线程池的理解吧. 那么,就以JDK1.8为例分析吧. 1.runWorker(Worker w) 工作线程启动后,就进入runWorker(Worker w)方法. 里面是一个while循环,循环判断任务是否为空,若不为空,执行任务:若取不到任务,或发生异

  • java线程池中线程数量到底是几

    目录 线程池配置 线程池里的业务线程数量小于最小数量(5) 第一个请求 第二个请求 第三个请求 第五个请求 小于阻塞队列容量(10) 第六个请求 第七个请求 第15个请求 小于最大数量(20) 第16个请求 第35个请求 拒绝策略 第36个请求 复用线程 线程池配置 线程池配置,假设是: 1.最小数量是5 2.阻塞队列容量是10 3.最大数量是20 线程池里的业务线程数量小于最小数量(5) 第一个请求 第一个请求进来的时候,这个时候,线程池没有线程,就创建新的工作线程(即Worker线程). 然

  • Java实现终止线程池中正在运行的定时任务

    最近项目中遇到了一个新的需求,就是实现一个可以动态添加定时任务的功能.说到这里,有人可能会说简单啊,使用quartz就好了,简单粗暴.然而quartz框架太重了,小项目根本不好操作啊.当然,也有人会说,jdk提供了timer的接口啊,完全够用啊.但是我们项目的需求完全是多线程的模型啊,而timer是单线程的,so,楼主最后还是选择了jdk的线程池. 线程池是什么 Java通过Executors提供四种线程池,分别为: newCachedThreadPool :创建一个可缓存线程池,如果线程池长度

  • Java线程池中的各个参数如何合理设置

    一.前言 在开发过程中,好多场景要用到线程池.每次都是自己根据业务场景来设置线程池中的各个参数. 这两天又有需求碰到了,索性总结一下方便以后再遇到可以直接看着用. 虽说根据业务场景来设置各个参数的值,但有些万变不离其宗,掌握它的原理对如何用好线程池起了至关重要的作用. 那我们接下来就来进行线程池的分析. 二.ThreadPoolExecutor的重要参数 我们先来看下ThreadPoolExecutor的带的那些重要参数的构造器. public ThreadPoolExecutor(int co

  • Java如何自定义线程池中队列

    目录 背景 问题分析 问题解决 总结 两个队列的UML关系图 SynchronousQueue的定义 ArrayBlockingQueue的定义 分析 jdk源码中关于线程池队列的说明 背景 业务交互的过程中涉及到了很多关于SFTP下载的问题,因此在代码中定义了一些线程池,使用中发现了一些问题, 代码类似如下所示: public class ExecutorTest { private static ExecutorService es = new ThreadPoolExecutor(2, 1

随机推荐