Java使用线程池和线程工厂

本文详细解析了Java线程池的工作原理及配置方法,通过具体示例演示了线程池如何处理任务,包括核心线程数、最大线程数、工作队列、拒绝策略等关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.uno.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;

/**
 * 线程池测试
 * @author uno
 *	5:coreThreadCount:核心线程数,即前5个线程来了就创建线程,加入线程池
 *	10:maxthreadCount:最大线程数,当core满时,会向workBlockQueue加入线程,等待执行
 *	new ArrayBlockingQueue(5):当blockqueue中满,会根据maxThreadCount再创建加入线程池
 *	当maxThreadCount满时,RejectedExecutionHandler拒绝策略上场
 *	shutdown:关闭线程池,等待缓存队列中线程执行完成
 *	shutdownNow:立即关闭线程池
 */

/**
 *  引用网上一段话
 *  1.当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 
	2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 
	3.当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 
	4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 
	5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 
	6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭
 * @author uno
 *
 */
public class ThreadPool {

	private static ThreadPoolExecutor executor = null;
	static {
		executor = new ThreadPoolExecutor(5, 10, 200, 
				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5), new MyTaskThreadFactory(), new AbortPolicy()
				);
		executor.prestartCoreThread(); //预启动一个线程
//		executor.prestartAllCoreThreads();//预启动corePoolSize个线程到线程池
	}
	
	
	public static void main(String[] args) {
		System.out.println("线程池线程数: "+executor.getPoolSize());
		for(int i = 0; i<15;i++){
			System.out.println(executor.isShutdown());
			executor.execute(new MyTask(i, "uno线程:"+i));
			System.out.println("线程池线程数: "+executor.getPoolSize());
			System.out.println("阻塞队列中线程数:" + executor.getQueue().size());
			System.out.println("已执行完线程数:" + executor.getCompletedTaskCount());
		}
		executor.shutdown(); //关闭线程池
	}
	
	
}
/**
 * 自定义线程工厂
 * @author uno
 * 
 */
class MyTaskThreadFactory implements ThreadFactory{
	private static String FACTORYNAME = "MYTASKFACTORY";
	private static List<? super Thread> threadList = new ArrayList<>();
	
	public void setFactoryName(String name){
		FACTORYNAME = name;
	}
	@Override
	public Thread newThread(Runnable r) {
		synchronized (r) {
			//这里可以自定义个Thread,用了处理在创建线程前后预处理
			Thread t = new Thread(r, FACTORYNAME + threadList.size());
			threadList.add(t);
			return t;
		}
	}
}
/**
 * 任务线程类
 * @author uno
 * 区别于线程工厂创建的线程:线程工厂创建的线程是用来执行任务线程(MyTask)的线程
 */
class MyTask extends Thread {
	private int num;
	public MyTask(int i, String name) {
		super(name);
		this.num = i;
	}
	@Override
	public void run() {
		try {
			System.out.println(this.getName() + ", 正执行task " + num);
			Thread.sleep(2000);
		} catch (Exception e) {
		}
		System.out.println(this.getName() + ", task " + num + " 执行完成");
	}
}



输出结果:

线程池线程数: 1
false
线程池线程数: 2
阻塞队列中线程数:0
线程0, 正执行task 0
已执行完线程数:0
false
线程池线程数: 3
阻塞队列中线程数:0
线程1, 正执行task 1
已执行完线程数:0
false
线程池线程数: 4
阻塞队列中线程数:0
线程2, 正执行task 2
已执行完线程数:0
false
线程池线程数: 5
阻塞队列中线程数:0
已执行完线程数:0
false
线程3, 正执行task 3
线程池线程数: 5
阻塞队列中线程数:0
已执行完线程数:0
false
线程4, 正执行task 4
线程池线程数: 5
阻塞队列中线程数:1
已执行完线程数:0
false
线程池线程数: 5
阻塞队列中线程数:2
已执行完线程数:0
false
线程池线程数: 5
阻塞队列中线程数:3
已执行完线程数:0
false
线程池线程数: 5
阻塞队列中线程数:4
已执行完线程数:0
false
线程池线程数: 5
阻塞队列中线程数:5
已执行完线程数:0
false
线程池线程数: 6
阻塞队列中线程数:5
线程10, 正执行task 10
已执行完线程数:0
false
线程池线程数: 7
阻塞队列中线程数:5
已执行完线程数:0
false
线程11, 正执行task 11
线程池线程数: 8
阻塞队列中线程数:5
已执行完线程数:0
false
线程12, 正执行task 12
线程池线程数: 9
阻塞队列中线程数:5
已执行完线程数:0
false
线程13, 正执行task 13
线程池线程数: 10
阻塞队列中线程数:5
已执行完线程数:0
线程14, 正执行task 14
线程0, task 0 执行完成
线程3, task 3 执行完成
线程2, task 2 执行完成
线程1, task 1 执行完成
线程7, 正执行task 7
线程6, 正执行task 6
线程10, task 10 执行完成
线程5, 正执行task 5
线程9, 正执行task 9
线程4, task 4 执行完成
线程11, task 11 执行完成
线程12, task 12 执行完成
线程8, 正执行task 8
线程14, task 14 执行完成
线程13, task 13 执行完成
线程7, task 7 执行完成
线程9, task 9 执行完成
线程5, task 5 执行完成
线程6, task 6 执行完成
线程8, task 8 执行完成
正好印证了上面的

 1.当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 
2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 
3.当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 
4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 
5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 
6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

<think>我们正在讨论Java中的线程工厂(ThreadFactory)线程池工厂(ThreadPoolFactory)的实现使用细节。根据引用内容,我们可以从ForkJoinPool中的线程工厂(ForkJoinWorkerThreadFactory)入手,因为引用[1][2]提到了ForkJoinPoolForkJoinWorkerThread。线程工厂(ThreadFactory)是一个用于创建新线程的接口。在Java中,java.util.concurrent.ThreadFactory接口只有一个方法:`ThreadnewThread(Runnabler)`。它的主要目的是允许开发人员自定义线程的创建过程,例如设置线程名称、优先级、守护线程状态等。对于线程池工厂,通常没有标准的接口,但我们可以通过Executors类提供的静态工厂方法来创建不同类型的线程池(如newFixedThreadPool,newCachedThreadPool等)。这些方法内部使用了默认的线程工厂,但也可以传入自定义的ThreadFactory。实现细节:1.自定义ThreadFactory:我们可以实现ThreadFactory接口,在newThread方法中创建线程并设置所需的属性。2.在创建线程池时,可以传入自定义的ThreadFactory。下面我们结合引用内容中的ForkJoinWorkerThreadFactory(这是ForkJoinPool中专用的线程工厂)来举例说明。在引用[1]中,ForkJoinPool的createWorker方法使用了factory(即ForkJoinWorkerThreadFactory)来创建新的工作线程(ForkJoinWorkerThread)。代码片段如下:```javaprivatebooleancreateWorker(){ForkJoinWorkerThreadFactoryfac=factory;Throwableex=null;ForkJoinWorkerThreadwt=null;try{if(fac!=null&&(wt=fac.newThread(this))!=null){wt.start();returntrue;}}catch(Throwablerex){ex=rex;}deregisterWorker(wt,ex);returnfalse;}```这里,factory是ForkJoinWorkerThreadFactory的一个实例,它负责创建新的ForkJoinWorkerThread。然后启动这个线程。ForkJoinWorkerThreadFactory是一个接口,它只有一个方法:```javapublicForkJoinWorkerThreadnewThread(ForkJoinPoolpool);```因此,我们可以通过实现这个接口来自定义ForkJoinWorkerThread的创建。使用示例:1.自定义一个线程工厂(以普通的ThreadFactory为例):```javaimportjava.util.concurrent.ThreadFactory;publicclassCustomThreadFactoryimplementsThreadFactory{privateintthreadCount=0;@OverridepublicThreadnewThread(Runnabler){threadCount++;Threadthread=newThread(r,"CustomThread-"+threadCount);thread.setDaemon(false);//设置为非守护线程thread.setPriority(Thread.NORM_PRIORITY);returnthread;}}```2.使用自定义线程工厂创建线程池:```javaimportjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassThreadFactoryExample{publicstaticvoidmain(String[]args){ThreadFactorycustomThreadFactory=newCustomThreadFactory();ExecutorServiceexecutor=Executors.newFixedThreadPool(3,customThreadFactory);//提交任务executor.submit(()->System.out.println("Taskexecutedby"+Thread.currentThread().getName()));executor.shutdown();}}```对于ForkJoinPool,我们可以自定义ForkJoinWorkerThreadFactory:```javaimportjava.util.concurrent.ForkJoinPool;importjava.util.concurrent.ForkJoinWorkerThread;publicclassCustomForkJoinWorkerThreadFactoryimplementsForkJoinWorkerThreadFactory{@OverridepublicForkJoinWorkerThreadnewThread(ForkJoinPoolpool){returnnewCustomForkJoinWorkerThread(pool);}}classCustomForkJoinWorkerThreadextendsForkJoinWorkerThread{publicCustomForkJoinWorkerThread(ForkJoinPoolpool){super(pool);//设置线程名称等setName("CustomForkJoinWorker-"+this.getPoolIndex());}}```然后使用这个工厂创建ForkJoinPool:```javaForkJoinPool.ForkJoinWorkerThreadFactoryfactory=newCustomForkJoinWorkerThreadFactory();ForkJoinPoolpool=newForkJoinPool(Runtime.getRuntime().availableProcessors(),factory,null,false);```注意事项:-在自定义线程时,要注意线程的命名,这样便于调试监控。-可以设置线程的异常处理器(UncaughtExceptionHandler)来处理线程中未捕获的异常。-对于ForkJoinPool,我们通常不需要直接创建线程工厂,因为默认的已经足够,但在需要特殊控制(如设置线程上下文类加载器)时,自定义工厂很有用。引用说明:-引用[1]展示了ForkJoinPool中createWorker方法使用线程工厂创建线程的过程[^1]。-引用[2]说明了ForkJoinPool中每个工作线程有自己的任务队列以及工作窃取机制[^2]。-引用[3]展示了ForkJoinTask的使用(如Fibonacci任务),但未直接涉及线程工厂[^3]。-引用[4]是关于邮件导出的性能优化,与线程工厂无关[^4]。因此,我们主要参考了引用[1][2]来阐述ForkJoinPool中线程工厂使用。相关问题:1.线程工厂(ThreadFactory)在Java并发编程中有什么作用?2.如何为不同的线程池(如ThreadPoolExecutor、ForkJoinPool)提供自定义的线程工厂?3.在自定义线程工厂时,有哪些常见的配置项(如线程名称、优先级、守护状态)?4.线程工厂在异常处理方面可以做什么?</think>### Java线程工厂线程池工厂的实现与使用 #### 一、线程工厂(ThreadFactory) 线程工厂是`java.util.concurrent.ThreadFactory`接口,用于**自定义线程创建过程**。核心方法是: ```java Thread newThread(Runnable r); ``` **实现示例**: ```java import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; public class CustomThreadFactory implements ThreadFactory { private final String namePrefix; private final AtomicInteger threadCount = new AtomicInteger(1); public CustomThreadFactory(String poolName) { this.namePrefix = "pool-" + poolName + "-thread-"; } @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, namePrefix + threadCount.getAndIncrement()); thread.setDaemon(false); // 非守护线程 thread.setPriority(Thread.NORM_PRIORITY); // 默认优先级 thread.setUncaughtExceptionHandler((t, e) -> System.err.println("Uncaught exception in " + t.getName() + ": " + e)); return thread; } } ``` **使用场景**: 1. **线程命名**:便于日志跟踪(如`pool-1-thread-2`) 2. **守护线程控制**:避免主线程退出时意外终止 3. **异常处理**:统一捕获未处理异常 4. **线程优先级设置**:区分关键任务 #### 二、线程池工厂 Java通过`Executors`类提供**线程池工厂方法**,内部使用`DefaultThreadFactory`: **常用工厂方法**: ```java // 固定大小线程池使用自定义线程工厂) ExecutorService fixedPool = Executors.newFixedThreadPool( 4, new CustomThreadFactory("fixed-pool") ); // 工作窃取线程池(ForkJoinPool) ForkJoinPool forkJoinPool = new ForkJoinPool( Runtime.getRuntime().availableProcessors(), new CustomForkJoinThreadFactory(), // 需实现ForkJoinWorkerThreadFactory null, false ); ``` #### 三、ForkJoinPool的线程工厂实现 引用[1]中的`createWorker()`方法展示了ForkJoinPool如何通过线程工厂创建工作线程[^1]: ```java private boolean createWorker() { ForkJoinWorkerThreadFactory fac = factory; ForkJoinWorkerThread wt = null; try { if (fac != null && (wt = fac.newThread(this)) != null) { wt.start(); // 启动工作线程 return true; } } catch (Throwable ex) { deregisterWorker(wt, ex); // 异常处理 } return false; } ``` **自定义ForkJoin线程工厂**: ```java import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinWorkerThread; public class CustomForkJoinThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory { @Override public ForkJoinWorkerThread newThread(ForkJoinPool pool) { return new CustomForkJoinWorkerThread(pool); } } class CustomForkJoinWorkerThread extends ForkJoinWorkerThread { protected CustomForkJoinWorkerThread(ForkJoinPool pool) { super(pool); // 设置线程名称/上下文等 setName("fj-worker-" + this.getPoolIndex()); } } ``` #### 四、关键设计原理 1. **工作窃取(Work-Stealing)** 引用[2]说明:每个工作线程有自己的任务队列,空闲时会窃取其他队列任务(FIFO顺序)[^2],提升CPU利用率。 2. **递归任务拆分** 如引用[3]的`Fibonacci`示例,通过`fork()`分解任务,`join()`合并结果[^3]: ```java class Fibonacci extends RecursiveTask<Integer> { protected Integer compute() { if (n <= 1) return n; Fibonacci f1 = new Fibonacci(n - 1); f1.fork(); // 异步执行子任务 Fibonacci f2 = new Fibonacci(n - 2); return f2.compute() + f1.join(); // 合并结果 } } ``` 3. **资源控制** - 通过线程工厂限制线程数量 - 避免过度拆分任务(如斐波那契例子的递归深度) #### 五、最佳实践 1. **命名规范**:线程名称包含池标识,便于监控 2. **异常处理**:防止未捕获异常导致线程退出 3. **上下文传递**:在`newThread()`中设置线程上下文(如类加载器、安全策略) 4. **避免阻塞**:ForkJoinPool任务应避免I/O阻塞 > **注意**:ForkJoinPool适用于计算密集型任务,I/O密集型场景应选用`ThreadPoolExecutor`。 --- ### 相关问题 1. 工作窃取(Work-Stealing)算法如何提升线程池性能? 2. 如何在自定义线程工厂中实现线程级监控(如任务执行耗时)? 3. ForkJoinPool与ThreadPoolExecutor的核心区别是什么? 4. 递归任务拆分时如何避免栈溢出问题? [^1]: `createWorker()`方法通过线程工厂创建并启动工作线程 [^2]: ForkJoinPool使用工作窃取机制优化任务分配 [^3]: 递归任务通过`fork()`/`join()`实现并行计算
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值