spring boot + multithreading practice (asynchronous + return value)

Don't be nonsense, just go ahead and do it, pay attention to the point, be sure to watch it at the end. 

Simplified processing in Springboot, only needs to configure a bean of type java.util.concurrent.TaskExecutor or its subclasses, and declare annotations in the configuration class or directly on the program entry class @EnableAsync.

The call is also simple, annotate the method of the object managed by Spring @Async, and the explicit call can take effect.

The following is an example of an asynchronous thread task with a return value: 

 Configuration class:

/**
 * @Description: The configuration class implements the AsyncConfigurer interface, and rewrites the getAsyncExecutor method, and returns a ThreadPoolTaskExecutor,
 * So we get a TaskExecutor based on the thread pool
 * Use @EnableAsync annotation to enable asynchronous task support
 * @ClassName: MultiThreadingConfig
 * @Author: xiaolege
 */
@Configuration
@ComponentScan("com.cn.geostar.api.*")
@EnableAsync
public class MultiThreadingConfig implements AsyncConfigurer{

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //Minimum number of threads
        taskExecutor.setCorePoolSize(5);
        //Maximum number of threads
        taskExecutor.setMaxPoolSize(10);
        //Waiting queue
        taskExecutor.setQueueCapacity(50);
        taskExecutor.setKeepAliveSeconds(600);
        //Set rejection policy
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //Wait for the end of all tasks before closing the thread pool
//        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
    }
    
}

service:

/**
 * @author xiaolege
 */
@Service
@ Slf4j
public class HarvestMultiThreadingService {

    /**
     * Table metadata information collection
     *
     * @Description: The @Async annotation indicates that the method is an asynchronous method,
     * If the annotation is at the class level, it means that all methods of this class are asynchronous methods, and the methods here are automatically injected using ThreadPoolTaskExecutor as TaskExecutor
     */
    @Async
    public Future<Boolean> executeAysncTableHarvest(BasicDataSource dataSource, String tableName){
        try{
            MetaLoader metaLoader = new MetaLoaderImpl(dataSource);
            Table tmd = metaLoader.getTable(tableName, SchemaInfoLevel.min());
            log.info(tmd.toString());
        } catch (Exception e){
            e.printStackTrace ();
            return new AsyncResult<>(false);
        }
        //Message summary
        return new AsyncResult<>(true);
    }
}

 

controller:

/**
 * @author xiaolege
 */
@RestController
@ Slf4j
public class TableController {

    @Autowired
    private HarvestMultiThreadingService harvestMultiThreadingService;

    @PostMapping("getTableMeta")
    public GeoResponse getTableMeta(String dataSourceId) throws ExecutionException, InterruptedException {
//        GeoResponse geoResponse = harvestProvider.getDataSourceInfo(dataSourceId);
        String url = "jdbc:mysql://127.0.0.1:3306/ceshi?user=root&password=123456&serverTimezone=GMT%2b8";
        String tableName = "test";
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setUrl(url);
        dataSource.setMaxActive(20);
        dataSource.setInitialSize (5);
        dataSource.setMinIdle(5);
        dataSource.setMaxWait(60000);
        int length = 50;
        List<Future<Boolean>> list = new ArrayList<>(50);
        for (int i = 0; i < length; i++) {
            try {
                Future<Boolean> future = harvestMultiThreadingService.executeAysncTableHarvest(dataSource,tableName);
                list.add(future);
            } catch (Exception e) {
                e.printStackTrace ();
            }
        }
        for (Future f:list
             ) {
            log.info(f.get().toString());
        }
        return GeoResponse.defaultSuccess();
    }
}

 

note: 

The Future generic interface is provided in java to receive task execution results. Springboot also provides such support, using classes that implement the ListenableFuture interface, such as AsyncResult, as the carrier of the return value. As shown in the example above.

If you don't want to return a value, just change the method in the service to void return.

Must pay attention to asynchronous tasks with return values

Be sure to read the results in batches, otherwise the asynchronous effect will not be achieved!!

1. The asynchronous method and the calling class should not be in the same class

2. When scanning annotations, pay attention to filtering to avoid repeated instantiations. Because of the coverage problem, @Async is invalid.

Guess you like

Origin blog.csdn.net/xiaolegeaizy/article/details/108224319
Recommended