为什么使用线程池?
- 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗;
- 提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行;
- 方便线程并发数的管控,因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换(cpu切换线程是有时间成本的(需要保持当前执行线程的现场,并恢复要执行线程的现场)
- 提供更强大的功能,延时定时线程池
参考博客:https://blog.csdn.net/u012060033/article/details/111934507
简单使用:
参考博客:https://blog.csdn.net/weixin_45866737/article/details/122539694
创建线程池
MyThreadPool .java
@Configuration
public class MyThreadPool {
//ThreadPoolTaskExecutor不会自动创建ThreadPoolExecutor,需要手动调initialize才会创建。如果@Bean就不需手动,会自动InitializingBean的afterPropertiesSet来调initialize
@Bean("myExecutor")
public Executor createJobExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 线程池活跃的线程数
executor.setCorePoolSize(20);
// 设置线程队列最大线程数
executor.setMaxPoolSize(40);
// 设置等待队列大小
executor.setQueueCapacity(200);
// 线程池维护线程所允许的空闲时间
executor.setKeepAliveSeconds(60);
// 线程前缀名称
executor.setThreadNamePrefix("myExecutor---: ");
executor.initialize();
return executor;
}
}
service层
@Service
public class StudentServiceImpl implements StudentService {
@Override
@Async("myExecutor")
public Future<StudentVo> toVo(Student student) {
StudentVo studentVo = StudentMapStruct.INSTANCE.studentToVo(student);
// 业务操作
return new AsyncResult<>(studentVo);
}
}
controller层:
@Api(tags = "学生实体类转vo接口")
@RestController
@RequestMapping(value = "/trans")
public class StudentController {
@Autowired
StudentServiceImpl studentService;
@ResponseBody
@PostMapping("/students")
@ApiOperation(value = "测试接口")
public ResponseEntity<StudentResponse> testStudent(@ApiParam("学生请求对象实体类") @RequestBody Student student){
Future<StudentVo> studentVo = studentService.toVo(student);
while (studentVo.isDone()) {
break;
}
StudentResponse studentResponse = StudentMapStruct.INSTANCE.voToResponse(studentVo.get());
return new ResponseEntity(studentResponse, HttpStatus.OK);
}
}
Future接口
Future接口通常与线程池一起使用。Future接口表示一个异步计算的结果,可以在计算完成之前返回。线程池可以将任务提交给线程池中的线程进行异步计算,并返回一个Future对象,以便在需要时获取计算结果。通过使用线程池和Future接口,可以实现并发编程,提高程序的性能和效率
Java Future接口有以下方法:
1. boolean cancel(boolean mayInterruptIfRunning):尝试取消任务的执行。如果任务已经完成或已经被取消,则返回false,否则返回true。如果mayInterruptIfRunning为true,则尝试中断任务的执行。
2. boolean isCancelled():如果任务已经被取消,则返回true,否则返回false。
3. boolean isDone():如果任务已经完成,则返回true,否则返回false。
4. V get() throws InterruptedException, ExecutionException:等待任务完成并返回结果。如果任务被取消,则抛出CancellationException。如果任务执行过程中出现异常,则抛出ExecutionException。如果等待过程中被中断,则抛出InterruptedException。
Future<Integer> future = executorService.submit(() -> {
// 执行一些耗时的操作
return 42;
});
try {
int result = future.get();
System.out.println("任务执行结果:" + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
5. V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException:等待任务完成并返回结果,但最多等待指定的时间。如果任务被取消,则抛出CancellationException。如果任务执行过程中出现异常,则抛出ExecutionException。如果等待过程中被中断,则抛出InterruptedException。如果超时,则抛出TimeoutException。
Future<Integer> future = executorService.submit(() -> {
// 执行一些耗时的操作
return 42;
});
try {
int result = future.get(1, TimeUnit.SECONDS);
System.out.println("任务执行结果:" + result);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
每个方法的代码示例:
import java.util.concurrent.*;
public class FutureExample {
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "Hello, World!";
});
// cancel方法示例
boolean cancelled = future.cancel(false);
System.out.println("Cancelled: " + cancelled);
// isCancelled方法示例
boolean isCancelled = future.isCancelled();
System.out.println("Is cancelled: " + isCancelled);
// isDone方法示例
boolean isDone = future.isDone();
System.out.println("Is done: " + isDone);
// get方法示例
String result = future.get();
System.out.println("Result: " + result);
// get方法超时示例
Future<String> futureWithTimeout = executor.submit(() -> {
Thread.sleep(2000);
return "Hello, World!";
});
String resultWithTimeout = futureWithTimeout.get(1, TimeUnit.SECONDS);
System.out.println("Result with timeout: " + resultWithTimeout);
executor.shutdown();
}
}