多个线程执行多个任务全部完成后统一返回 TaskExecutorConfig CountDownLatch

  • Post author:
  • Post category:其他


多线程实现的方式

java.util.concurrent 包下面的类 Executor

java.util.concurrent 包下面的类 ExecutorService pool = Executors.newCachedThreadPool(); 有4个静态方法可以创建不同的类型的线程池

springboot 项目里面可以利用框架封装的线程池和注解实现异步 这个是我们这次讲解的重点

首先配置类

@Component
@Configuration
public class TaskExecutorConfig implements AsyncConfigurer{

	@Override
	@Bean
	public Executor getAsyncExecutor() {
		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
		taskExecutor.setCorePoolSize(20);// 设置核心的线程数量
		taskExecutor.setMaxPoolSize(50);// 设置最大的线程数量
		taskExecutor.setKeepAliveSeconds(8);//空闲时间s
		taskExecutor.setAwaitTerminationSeconds(3);//等待阻塞最长时间s
		taskExecutor.initialize();// 初始化
		taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		return taskExecutor;
	}

	@Override
	public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return new ExceptionHandlingAsyncTaskExecutor();
	}

}

定义子线异常的处理方法 多线程执行的时候子线程的异常不会每次都能够打印出来 需要配置这个类来打印子线程的异常

@Component
@Configuration
public class ExceptionHandlingAsyncTaskExecutor implements AsyncUncaughtExceptionHandler{
	
private static final Logger logger  = LoggerFactory.getLogger(ExceptionHandlingAsyncTaskExecutor.class);

	@Override
	public void handleUncaughtException(Throwable ex, Method method, Object... params) {
		logger.info("Method name - " + method.getName());
		logger.info("Exception message - " + ex.getMessage());
         for (Object param : params) {
        	 logger.info("Parameter value - " + param);
         }  
     }  
	
}

启动类上面增加配置

@EnableAsync
@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	
}
让方法异步执行只有一个注解就可以 @Async 主线程只想到这个方法的时候回就回创建一个新的线程
    @Async
    @Override
    public List getMbiIndex(CountDownLatch downLatch) {
        downLatch.countDown();
    }
情景:给前段返回多个数据 请求多个service里面的多个方法 每个方法都是异步的,主线程等待异步的线程执行完毕之后统一返回给前段

这里需要用到一个对象 CountDownLatch

// 构造方法 cout需要计数的线程的个数
 public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }


// 等待所有计算都清零再继续执行 
public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
// 等待所有记录都清零再执行 规定时间内没有清零就不再等待
    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

//线程清理计数的功能 每个子线程完成任务执行这方法就可以清楚该线程的计数

    public void countDown() {
        sync.releaseShared(1);
    }

主方法

public Object mian(){

CountDownLatch downLatch= new CountDownLatch(3);

Future<List> list1=test1(downLatch)

Future<List> list2=test2(downLatch)

Future<List> list3=test3(downLatch)

downLatch.await(4L, TimeUnit.SECONDS);

return  list1.get();

}

Future<List> test1(CountDownLatch downLatch){

………

downLatch.countDown();


return

new AsyncResult<List>(new ArrayList());

}

test2() 和 test3()也是要调用这个downLatch.countDown();



版权声明:本文为sswltt原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。