springboot异步线程(一)

该图片由mac231在Pixabay上发布

前言

在本篇文章中,我们主要讨论spring异步编程的一些相关知识,不涉及实战。springboot版本2.2.1

TaskExecutor

spring2.0后提出TaskExecutor接口,作为任务执行者抽象。TaskExecutor源码:

1
2
3
4
5
6
7
8

@FunctionalInterface
public interface TaskExecutor extends Executor {
	@Override
	void execute(Runnable task);

}

spring框架提供了一定的TaskExecutor实现类,这些实现类可以完成几乎所有使用场景的覆盖,所以,大多数情况下,我们没有必要实现某个TaskExecutor

  1. SyncTaskExecutor
    代码如下:
1
2
3
4
5
6
7
8
9
10

public class SyncTaskExecutor implements TaskExecutor, Serializable {
	@Override
	public void execute(Runnable task) {
		Assert.notNull(task, "Runnable must not be null");
		task.run();
	}

}

可以发现,提交给SyncTaskExecutor的任务都是直接在当前线程中执行

  1. SimpleAsyncTaskExecutor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    @Override
	public void execute(Runnable task, long startTimeout) {
		Assert.notNull(task, "Runnable must not be null");
		Runnable taskToUse = (this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
		if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
			this.concurrencyThrottle.beforeAccess();
			doExecute(new ConcurrencyThrottlingRunnable(taskToUse));
		}
		else {
			doExecute(taskToUse);
		}
	}
	
	protected void doExecute(Runnable task) {
		Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
		thread.start();
	}

提交给SimpleAsyncTaskExecutor的任务每次都新建一个线程来执行提交的任务。

  1. ThreadPoolTaskExecutor
    如果觉得SimpleAsyncTaskExecutor每次都需要新建线程不可取,就可以使用这个,ThreadPoolTaskExecutor改用线程池来管理并重用处理任务异步执行的工作线程。其中,ThreadPoolTaskExecutor的线程池功能是使用的jdk的ThreadPoolExecutor来实现的。
1
2
3
4
5
6
7
8
9
10
11
12

@Override
	public void execute(Runnable task) {
		Executor executor = getThreadPoolExecutor();
		try {
			executor.execute(task);
		}
		catch (RejectedExecutionException ex) {
			throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
		}
	}

  1. ConcurrentTaskExecutor
    ConcurrentTaskExecutorJava5ExecutorspringTaskExecutor搭建了一道桥梁使得我们可以将Executor框架下的某些实现类以TaskExecutor的形式公开来,如果我们感觉ThreadPoolTaskExecutor封装的java.util.concurrent.ThreadPoolExecutor不足以満足当前场景需要,那么可以构建需要的Executor实例,比如通过Executors.newXXXThreadPool(),然后以ConcurrentTaskExecutor对其进行封装,封装后获得的ConcurrentTaskExecutor即获得相应Executor的能力,但它现在是以TaskExecutor的样子示人气如下所示:
1
2
3
4

Executor executor =Executors .newScheduledThreadPool (10);
TaskExecutor taskExecutor = new ConcurrentTaskExecutor (executor):

最后

异步线程的一些相关知识知道了。接下来就是怎么去使用了。

参考:

  1. Spring Boot Async Task Executor
  2. Spring 官方文档
  3. 新手也能看懂的 SpringBoot 异步编程指南
  4. TaskExecutionAutoConfiguration
坚持原创技术分享,您的支持将鼓励我继续创作!