Java多线程之~~~使用ThreadPoolExecutor来创建线程

本文介绍如何利用Java的线程池技术优化多线程任务的执行,通过实例展示如何创建并管理线程池,提高系统性能并避免资源浪费。

以前我们创建线程的时候都是主动的new一个Thread,然后调用他们的start方法,但是如果线程非常多,任务也非

常多的时候,这样写就会显得非常麻烦,当然可能效率也不是很高,Java给我们提供了叫线程创建器这个样概念的类,

他可以帮助我们管理这些线程,你做的就是编写好代码,然后交给他,她就会自动帮你运行。

当然,带cache的threadpool 对于死掉的线程重新调用,在性能上也会有非常好的表现,但是不能将太多的线程交

给他管理,否则就会把系统拖垮,下面我们来做一个例子。

package com.bird.concursey.charpet6;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Task implements Runnable {
	// store the creation date of the task
	private Date initDate;
	// store the name of the task
	private String name;

	public Task(String name) {
		this.initDate = new Date();
		this.name = name;
	}

	@Override
	public void run() {
		System.out.printf("%s: Task %s: Created on: %s\n", Thread
				.currentThread().getName(), name, initDate);
		System.out.printf("%s: Task %s: Started on: %s\n", Thread
				.currentThread().getName(), name, new Date());

		try {
			Long duration = (long) (Math.random() * 10);
			System.out.printf("%s: Task %s: Doing a task during %d seconds\n",
					Thread.currentThread().getName(), name, duration);
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.printf("%s: Task %s: Finished on: %s\n",Thread.
				currentThread().getName(),name,new Date());
	}
}

package com.bird.concursey.charpet6;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * execute every task it receives using an executor
 * 
 * @author bird 2014年9月23日 下午9:03:01
 */
public class Server {
	private ThreadPoolExecutor executor;

	public Server() {
		executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
	}

	public void executeTask(Task task) {
		System.out.printf("Server: A new task has arrived\n");
		executor.execute(task);
		System.out.printf("Server: Pool Size: %d\n", executor.getPoolSize());
		System.out.printf("Server: Active Count: %d\n",
				executor.getActiveCount());
		System.out.printf("Server: Completed Tasks: %d\n",
				executor.getCompletedTaskCount());
	}
	
	public void endServer() {
		executor.shutdown();
	}
	
	public static void main(String[] args) {
		Server server = new Server();
		for(int i = 0; i < 100; i++) {
			Task task = new Task("Task" + i);
			server.executeTask(task);
		}
		server.endServer();
	}
}


如果有大量的线程进入,他会给每一个线程创建一个对象,这样就会令系统不堪重负,Executors提供了一种构造方

法,设置一个最大量,如果创建的线程数量超过了这个数量,Executors就不会再去创建这个线程,等待已经在线程池

里面的线程运行完了,有空闲的位置了才去继续创建新线程,这样就会让系统变的健壮。


上面的代码都不需要该,我们只需要在构造函数的地方重新实例化一个 代码如下

	public Server() {
		executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
	}


<think>我们正在讨论Java中如何使用ThreadPoolExecutor创建线程。根据之前的对话历史和引用内容,用户已经了解ThreadPoolExecutor的基本参数和创建方式,现在需要详细的创建步骤和示例。 引用[1]和[2]介绍了ThreadPoolExecutor的构造函数参数,引用[3]对比了Executors工厂方法和ThreadPoolExecutor,引用[4]展示了使用Callable和Future的示例,引用[5]提到了在Spring Boot中配置线程池。 因此,回答应该包括以下要点: 1. ThreadPoolExecutor构造函数参数详解(参考引用[1][2]) 2. 创建步骤:包括对象实例化和任务提交(execute和submit) 3. 完整示例代码(参考引用[4]并改进,同时展示无返回值和有返回值任务) 4. 线程池关闭方法(shutdown和shutdownNow) 5. 在Spring Boot中配置线程池的简要说明(参考引用[5]) 注意:根据用户要求,使用中文回答,并确保LaTeX格式正确,同时末尾生成相关问题。 </think>### Java使用ThreadPoolExecutor创建线程的完整指南 #### 一、线程池创建步骤 1. **导入核心包** ```java import java.util.concurrent.*; ``` 2. **配置关键参数**(参考引用[1][2]) ```java int corePoolSize = 4; // 核心线程数(常驻线程) int maxPoolSize = 10; // 最大线程数 long keepAliveTime = 60; // 非核心线程空闲存活时间 TimeUnit unit = TimeUnit.SECONDS; BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(100); // 任务队列 RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); // 拒绝策略 ``` 3. **实例化线程池** ```java ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, unit, queue, Executors.defaultThreadFactory(), // 线程工厂 handler ); ``` > **参数说明**: > - `corePoolSize`:常驻核心线程数(即使空闲也不回收) > - `maxPoolSize`:线程池最大容量(含核心线程) > - `keepAliveTime`:非核心线程空闲回收时间阈值 > - `queue`:推荐有界队列(如`ArrayBlockingQueue`)防止OOM[^3] #### 二、提交任务的两种方式 1. **无返回值任务(`Runnable`接口)** ```java executor.execute(() -> { System.out.println("线程ID:" + Thread.currentThread().getId()); // 执行具体任务逻辑 }); ``` 2. **有返回值任务(`Callable`接口)**(参考引用[4]) ```java Future<String> future = executor.submit(() -> { Thread.sleep(1000); return "任务结果"; }); // 阻塞获取结果 String result = future.get(); System.out.println("Result: " + result); ``` #### 三、完整示例代码 ```java public class ThreadPoolDemo { public static void main(String[] args) throws Exception { // 1. 创建线程池 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 核心线程数 5, // 最大线程数 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10) ); // 2. 提交任务 for (int i = 0; i < 15; i++) { final int taskId = i; executor.execute(() -> { System.out.printf("任务%d 由线程%d执行%n", taskId, Thread.currentThread().getId()); }); } // 3. 关闭线程池 executor.shutdown(); if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } } ``` #### 四、核心机制解析 1. **任务调度流程**: - 新任务优先使用核心线程执行 - 核心线程满载 → 任务进入阻塞队列 - 队列满载 → 创建非核心线程(不超过`maxPoolSize`) - 线程和队列均满 → 触发拒绝策略[^2] 2. **资源回收**: ```java // 允许回收核心线程(默认不回收) executor.allowCoreThreadTimeOut(true); ``` - 非核心线程超过`keepAliveTime`空闲即销毁 - 核心线程默认常驻(需手动开启回收)[^5] #### 五、Spring Boot集成示例(参考引用[5]) ```java @Configuration public class ThreadPoolConfig { @Bean public ThreadPoolExecutor taskExecutor() { return new ThreadPoolExecutor( 4, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100) ); } } // 业务层调用 @Service public class TaskService { @Autowired private ThreadPoolExecutor executor; public void runTask() { executor.execute(() -> { // 业务逻辑 }); } } ``` > **最佳实践**: > - CPU密集型任务:线程数 ≈ CPU核数 > - IO密集型任务:线程数 = CPU核数 × (1 + 等待时间/计算时间)[^2] > - 监控指标:`executor.getActiveCount()`(活动线程数)、`executor.getQueue().size()`(队列积压量)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值