首页 > 工作 > 对ThreadPoolExecutor线程启动时机的误解

对ThreadPoolExecutor线程启动时机的误解

为了便于简化日志,上一个小一些的数字

	private final static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 3, 60L, TimeUnit.SECONDS, //
			new ArrayBlockingQueue(5), //
			new TestThreadFactory(), //
			new TestRejectedHandler());

核心线程数是1,最大线程数是3。

按自然的理解方式,线程的规则应该是:在不超总线程数的基础上,尽最大可能让队列空。
也就是说:有三个需要同时处理的任务时,应该启用三个线程。

实测发现,它的规则是:仅在队列满的时候才触发创建新线程。
验证代码如下

package test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolTest {
	private final static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 3, 60L, TimeUnit.SECONDS, //
			new ArrayBlockingQueue(5), //
			new TestThreadFactory(), //
			new TestRejectedHandler());

	public static void main(String[] args) {
		for (int i = 1; i < 100000; i++) {
			threadPool.execute(new TestRun(i));
			try {
				log("加入" + i);
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private static class TestRun implements Runnable {
		public TestRun(int id) {
			this.id = id;
		}

		private int id;

		@Override
		public void run() {
			log(id + "开始。");
			try {
				Thread.sleep(10 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			log(id + "结束。");
		}

	}

	private static class TestThreadFactory implements ThreadFactory {
		private final AtomicInteger threadNumber = new AtomicInteger(0);

		public Thread newThread(Runnable r) {
			int n = threadNumber.incrementAndGet();
			if (n > 100000) {
				threadNumber.compareAndSet(n, 0);
			}
			Thread t = new Thread(r, "-" + n);
			if (t.isDaemon())
				t.setDaemon(false);
			if (t.getPriority() != Thread.NORM_PRIORITY)
				t.setPriority(Thread.NORM_PRIORITY);
			return t;
		}
	}

	private static class TestRejectedHandler implements RejectedExecutionHandler {
		@Override
		public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
			TestRun t = (TestRun) r;
			log(t.id + "被拒。");
		}
	}

	private static void log(String log) {
		System.out.println(log);
	}
}

执行的结果如下

加入1
1开始。
加入2
加入3
加入4
加入5
加入6
加入7
7开始。
加入8
8开始。
9被拒。
加入9
10被拒。
加入10
11被拒。
加入11
1结束。
2开始。
加入12
13被拒。
加入13
14被拒。
加入14
15被拒。
加入15
16被拒。
加入16
7结束。
17被拒。
加入17
3开始。
加入18
8结束。
4开始。
加入19
20被拒。
加入20

分类: 工作 标签:
  1. 本文目前尚无任何评论.