SpringBoot 使用 Future 实现多任务并行

1、先来说一下java中的Future模式

       在并发编程中,我们经常用到非阻塞的模型,在之前的多线程的三种实现中,不管是继承thread类还是实现runnable接口,都无法保证获取到之前的执行结果。通过实现Callback接口,并用Future可以来接收多线程的执行结果。

        Future表示一个可能还没有完成的异步任务的结果,针对这个结果可以添加Callback以便在任务执行成功或失败后作出相应的操作。

        举个例子:比如去吃早点时,点了包子和凉菜,包子需要等3分钟,凉菜只需1分钟,如果是串行的一个执行,在吃上早点的时候需要等待4分钟,但是因为你在等包子的时候,可以同时准备凉菜,所以在准备凉菜的过程中,可以同时准备包子,这样只需要等待3分钟。那Future这种模式就是后面这种执行模式。
 

2、现在来看代码,首先在SpringBoot主类中添加@EnableAsync 注解开启多任务

package com.api;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableAsync;


@SpringBootApplication
@EnableAutoConfiguration
@EnableAsync // 开启多任务
public class BaskApplication extends SpringBootServletInitializer {
	/**
	 * main方法启动进入swagger-u
	 * @param args
	 */
	public static void main(String[] args) {
		SpringApplication.run(BaskApplication.class, args);
	}
	/**
	 * Tomcat部署后启动(二者选其一,多余的进行注释)
	 */
	@Override
    protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
        return application.sources(BaskApplication.class);
        
    }
	

	
}

3、配置线程池的参数

package com.api.utils;

import java.util.concurrent.Executor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncTaskConfig implements AsyncConfigurer {
	
	
		// ThredPoolTaskExcutor的处理流程
		// 当池子大小小于corePoolSize,就新建线程,并处理请求
		// 当池子大小等于corePoolSize,把请求放入workQueue中,池子里的空闲线程就去workQueue中取任务并处理
		// 当workQueue放不下任务时,就新建线程入池,并处理请求,如果池子大小撑到了maximumPoolSize,就用RejectedExecutionHandler来做拒绝处理
		// 当池子的线程数大于corePoolSize时,多余的线程会等待keepAliveTime长时间,如果无请求可处理就自行销毁
		@Override
		public Executor getAsyncExecutor() {
			// 新建一个任务执行器
			ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
			taskExecutor.setCorePoolSize(2);// 设置最小的线程数量
			taskExecutor.setMaxPoolSize(5);// 设置最大的线程数量
			taskExecutor.setQueueCapacity(25);// 等待队列
			taskExecutor.initialize();// 初始化
			return taskExecutor;
		}
	 
		@Override
		public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
			return null;
		}
	

}

4、单独编写一个多任务执行的类(无返回值)

package com.api.serviceImpl;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class AsyncTaskService {
	
	
	// 没有返回值的异步调用
		@Async // 表明这异步方法 无返回值
		public void task1() {
			long s = System.currentTimeMillis();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long e = System.currentTimeMillis();
			System.out.println("tas1k总耗时:" + (e - s) + Thread.currentThread().getName());
			System.out.println("执行异步任务" + 1);
		}
	 
		@Async // 表明这异步方法 无返回值
		public void task2() {
			long s = System.currentTimeMillis();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long e = System.currentTimeMillis();
			System.out.println("tas2k总耗时:" + (e - s));
			System.out.println("执行异步任务" + 2 + Thread.currentThread().getName());
		}
	 
		@Async // 表明这异步方法 无返回值
		public void task3() {
			long s = System.currentTimeMillis();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long e = System.currentTimeMillis();
			System.out.println("tas3k总耗时:" + (e - s));
			System.out.println("执行异步任务" + 3 + Thread.currentThread().getName());
		}
	 
		@Async // 表明这异步方法 无返回值
		public void task5() {
			long s = System.currentTimeMillis();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long e = System.currentTimeMillis();
			System.out.println("tas5k总耗时:" + (e - s));
			System.out.println("执行异步任务" + 5 + Thread.currentThread().getName());
		}
	 
		@Async // 表明这异步方法 无返回值
		public void task4() {
			long s = System.currentTimeMillis();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			long e = System.currentTimeMillis();
			System.out.println("tas4k总耗时:" + (e - s));
			System.out.println("执行异步任务" + 4 + Thread.currentThread().getName());
		}

}

5、还可以编写带有返回值的异步方法;回调函数

package com.api.serviceImpl;

import java.io.File;
import java.util.concurrent.Future;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import com.aliyun.oss.OSSClient;

@Component
public class AsynTaskFature {

	@Async
	public Future<String> task1() throws InterruptedException {
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(0);
		long currentTimeMillis1 = System.currentTimeMillis();
		System.out.println("task1任务耗时:" + (currentTimeMillis1 - currentTimeMillis) + "ms");
//		System.out.println("开始1");
//		OOSManager("1");
		return new AsyncResult<String>("task1执行完毕");
	}
 
	@Async
	public Future<String> task2() throws InterruptedException {
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(0);
		long currentTimeMillis1 = System.currentTimeMillis();
		System.out.println("task2任务耗时:" + (currentTimeMillis1 - currentTimeMillis) + "ms");
//		System.out.println("开始2");
//		OOSManager("2");
		return new AsyncResult<String>("task2执行完毕");
	}
 
	@Async
	public Future<String> task3() throws InterruptedException {
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(0);
		long currentTimeMillis1 = System.currentTimeMillis();
//		System.out.println("开始3");
//		OOSManager("rfwDB3L");
		System.out.println("task3任务耗时:" + (currentTimeMillis1 - currentTimeMillis) + "ms");
		return new AsyncResult<String>("task3执行完毕");
	}
 
	@Async
	public Future<String> task4() throws InterruptedException {
		long currentTimeMillis = System.currentTimeMillis();
		Thread.sleep(3000);
		long currentTimeMillis1 = System.currentTimeMillis();
		System.out.println("task4任务耗时:" + (currentTimeMillis1 - currentTimeMillis) + "ms");
		return new AsyncResult<String>("task4执行完毕");
	}
	


	
}

6、在控制器中的调用

package com.api.controller;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.api.entity.User;
import com.api.service.InNumberService;
import com.api.serviceImpl.AsynTaskFature;
import com.api.serviceImpl.AsyncTaskService;

@Controller
@RequestMapping("/")
public class InNumberController {

	@Autowired
	InNumberService inNumberService;
	
	@Autowired
	AsyncTaskService asynService;
	
	@Autowired
	AsynTaskFature taskService;
	
	
	@RequestMapping(value="/test",method = RequestMethod.GET)
	@ResponseBody
    public long test(HttpServletResponse response) throws InterruptedException, ExecutionException {
		
		long s = System.currentTimeMillis();
//		Future<String> task1 = taskService.task1();
//		Future<String> task2 = taskService.task2();
		Future<String> task3 = taskService.task3();
		for (;;) {
			// 回调函数 Future 如果执行完毕就会返回这个函数
			if (task3.isDone()) {
				//System.out.println("task1");
				break;
			}
		}
//		System.out.println(task1.get());
//		System.out.println(task2.get());
		System.out.println(task3.get());
	
		
		long e = System.currentTimeMillis();
		System.out.println("task总耗时:" + (e - s));
		
		return  (e - s);
    }
}

 

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Spring Boot中,可以使用Java线程池来实现并行化处理。具体步骤如下: 1. 在Spring Boot的配置文件中配置线程池相关参数,例如线程池大小等。 2. 在需要并行化处理的方法上添加@Async注解,表示该方法将在另一个线程中异步执行。 3. 在调用需要并行化处理的方法时,使用Spring Boot的异步调用方式,例如CompletableFuture。 4. 在异步调用方法后,可以使用CompletableFuture的一些方法等待异步方法执行完毕,并获取结果。 示例代码如下: ```java // 1. 在配置文件中配置线程池 @Configuration @EnableAsync public class AppConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(100); executor.setQueueCapacity(10); executor.initialize(); return executor; } } // 2. 在需要并行化处理的方法上添加@Async注解 @Service public class MyService { @Async public CompletableFuture<String> doSomethingAsync() { // 需要异步执行的方法 return CompletableFuture.completedFuture("done"); } } // 3. 在调用需要并行化处理的方法时,使用异步调用方式 @RestController public class MyController { @Autowired private MyService myService; @GetMapping("/async") public CompletableFuture<String> async() { return myService.doSomethingAsync(); } } // 4. 在异步调用方法后,可以使用CompletableFuture的一些方法等待异步方法执行完毕,并获取结果 CompletableFuture<String> future = myService.doSomethingAsync(); String result = future.get(); ``` 这样就可以使用线程池实现Spring Boot的并行化处理了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值