Thread foundation and CompletableFuture asynchronous orchestration

Table of contents

1. Thread review

1. Four ways to initialize threads

2. Seven parameters of the thread pool

3. Four common thread pools

4. Why use thread pool in development

 2. CompletableFuture asynchronous arrangement

1. Create an asynchronous object

2. The callback method when the calculation is completed

3. handle method

4. Thread serialization method

5. Combination of two tasks - both must be completed

6. Combination of two tasks - one completed

7. Multitasking combination

8. Examples


1. Thread review

1. Four ways to initialize threads

1 ), inherit Thread
2 ) Implement the Runnable interface
3 ) Implement the Callable interface + FutureTask (you can get the returned result and handle exceptions)
4 ), thread pool
Mode 1 and Mode 2 : The main process cannot obtain the operation result of the thread.
Mode 3 : The main process can obtain the operation results of the threads, but it is not conducive to controlling the thread resources in the server. Can lead to exhaustion of server resources.
Method 4 : Initialize the thread pool in the following two ways
Executors.newFiexedThreadPool(3);
//或者
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit unit, workQueue, threadFactory, handler);
Through the stable performance of the thread pool, the execution result can also be obtained and the exception can be caught. However, in complex business situations, an asynchronous call may depend on the execution result of another asynchronous call.

2. Seven parameters of the thread pool

 

 

Running process:
1. Create a thread pool, prepare core threads with the number of cores , and prepare to accept tasks
2. A new task comes in and is executed with the idle thread prepared by the core .
(1) When the core is full, put the incoming tasks into the blocking queue. The idle core will block the queue to obtain task execution by itself
(2) When the blocking queue is full, a new thread will be opened directly for execution, and the maximum number can only be opened to the number specified by max
(3) and max are executed. The idle threads with the Max-core number will be automatically destroyed after the time specified by keepAliveTime . Finally keep to the core size
(4) If the number of threads reaches the max number and new tasks come in, the rejection strategy specified by reject will be used for processing
3. All thread creation is created by the specified factory
interview:
A thread pool core 7 ; max 20 , queue : 50 , 100 concurrent incoming how to allocate;
First, 7 of them can be executed directly, then 50 of them will enter the queue, and 13 more will continue to be executed. 70 now _
was arranged. There are 30 default deny policies remaining .

 3. Four common thread pools

  • 1、newCachedThreadPool
    • Create a cacheable thread pool. If the length of the thread pool exceeds the processing needs, the idle thread can be recycled flexibly. If there is no recycling, a new thread will be created.
  • 2、newFixedThreadPool
    • Create a fixed-length thread pool, which can control the maximum number of concurrent threads, and the excess threads will wait in the queue.
  • 3、newScheduledThreadPool
    • Create a fixed-length thread pool to support timing and periodic task execution.
  • 4、newSingleThreadExecutor
    • Create a single-threaded thread pool, which will only use the only worker thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority ) .

 

4. Why use thread pool in development

1. Reduce resource consumption
  • Reduce the loss caused by thread creation and destruction by reusing already created threads
2. Improve response speed
  • Because when the number of threads in the thread pool does not exceed the maximum limit of the thread pool, some threads are in the state of waiting for assignment tasks, and when tasks come, they can be executed without creating new threads.
3. Improve thread manageability
  • The thread pool will optimize the threads in the pool according to the current system characteristics, reducing the system overhead caused by creating and destroying threads. Unlimited creation and destruction of threads not only consumes system resources, but also reduces the stability of the system, using the thread pool for unified allocation

 2. CompletableFuture asynchronous arrangement

Future is a class added by Java 5 to describe the result of an asynchronous calculation. You can use the `isDone` method to check whether the calculation is complete, or use `get` to block the calling thread until the calculation is completed and return the result, you can also use the `cancel` method to stop the execution of the task.
Although `Future` and related usage methods provide the ability to execute tasks asynchronously, it is very inconvenient to obtain the results, and the results of the tasks can only be obtained by blocking or polling. The blocking method is obviously contrary to our original intention of asynchronous programming. The polling method will consume unnecessary CPU resources, and the calculation result cannot be obtained in time. Why can't the observer design mode be used to notify the listener in time when the calculation result is completed? Woolen cloth?
Many languages, such as Node.js , use callbacks to implement asynchronous programming. Some Java frameworks, such as Netty , extend Java ’s `Future` interface and provide multiple extension methods such as `addListener` ; Google guava also provides a general extended Future ; Scala also provides an easy-to-use and powerful Future/Promise asynchronous programming mode.
As an orthodox Java class library, should we do something to enhance the functions of our own library?
In Java 8 , a new class with about 50 methods has been added : CompletableFuture , which provides a very powerful extension function of Future, which can help us simplify the complexity of asynchronous programming, and provides the ability of functional programming, which can be passed through callback CompletableFutures are processed in the same way, and methods for converting and combining CompletableFutures are provided. The CompletableFuture class implements the Future interface, so you can still get the result by blocking or polling the `get` method as before , but this method is not recommended.
Both CompletableFuture and FutureTask belong to the implementation class of the Future interface, and both can obtain the execution results of threads.

 1. Create an asynchronous object

CompletableFuture provides four static methods to create an asynchronous operation.
1. runXxxx does not return a result, and supplyXxx can obtain a return result
2. You can pass in a custom thread pool, otherwise use the default thread pool;

 

2. The callback method when the calculation is completed

whenComplete can handle normal and abnormal calculation results, and exceptionally handles abnormal conditions.
The difference between whenComplete and whenCompleteAsync :
  • whenComplete : The thread that executes the current task executes the task that continues to execute whenComplete .
  • whenCompleteAsync : It is to execute the task of whenCompleteAsync to continue to submit to the thread pool for execution.
The method does not end with Async , which means that Action uses the same thread to execute, and Async may use other threads to execute (if it uses the same thread pool, it may also be selected for execution by the same thread)
public class CompletableFutureDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<Object>() {
            @Override
            public Object get() {
                System.out.println(Thread.currentThread().getName() + "\t
                        completableFuture");
                int i = 10 / 0;
                return 1024;
            }
        }).whenComplete(new BiConsumer<Object, Throwable>() {
            @Override
            public void accept(Object o, Throwable throwable) {
                System.out.println("-------o=" + o.toString());
                System.out.println("-------throwable=" + throwable);
            }
        }).exceptionally(new Function<Throwable, Object>() {
            @Override
            public Object apply(Throwable throwable) {
                System.out.println("throwable=" + throwable);
                return 6666;
            }
        });
        System.out.println(future.get());
    }
}

3. handle method _

Like complete , it can do final processing on the result (can handle exceptions), and can change the return value.

4. Thread serialization method

 

thenApply method: When a thread depends on another thread, get the result returned by the previous task and return the return value of the current task.
thenAccept method: Consume processing results. Receive the processing result of the task, and consume the processing, and return no result.
thenRun method: As long as the above task is executed, thenRun will be executed , and only after the task is processed, the follow-up operation of thenRun will be executed
With Async it is executed asynchronously by default. Same as before.
All of the preceding tasks must be successfully completed.
Function<? super T,? extends U>
  • T : the type of the result returned by the previous task
  • U : the return value type of the current task

 5. Combination of two tasks - must be completed

  

Both tasks must be completed to trigger this task.
thenCombine : Combine two futures , get the return results of the two futures , and return the return value of the current task
thenAcceptBoth : Combine two futures , get the return results of the two future tasks, and then process the tasks without returning a value.
runAfterBoth : Combining two futures , no need to get the results of the futures , only need to process the task after the two futures have finished processing the task.

6. Combination of two tasks - one completed

 

When any of the future tasks in the two tasks is completed, the task is executed.
applyToEither : One of the two tasks is executed, gets its return value, processes the task and has a new return value.
acceptEither : One of the two tasks is executed, get its return value, process the task, and there is no new return value.
runAfterEither : One of the two tasks is executed, there is no need to get the result of the future , process the task, and there is no return value.

7. Multi-tasking combination

allOf : wait for all tasks to complete
anyOf : as long as there is one task completed

8. Examples

    @Override
    public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {


        SkuItemVo vo = new SkuItemVo();

        CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
            // 1、sku的基本信息获取 pms_sku_info
            SkuInfoEntity info = getById(skuId);
            vo.setInfo(info);
            return info;
        }, executor);

        CompletableFuture<Void> imgFuture = CompletableFuture.runAsync(() -> {
            // 2、sku的图片信息 pms_sku_img
            List<SkuImagesEntity> images = skuImagesService.getImagesBySkuId(skuId);
            vo.setImages(images);
        }, executor);

        CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync((res) -> {
            // 3、获取spu的销售属性组合
            List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(res.getSpuId());
            vo.setSaleAttr(saleAttrVos);
        }, executor);


        CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync((res) -> {
            // 4、获取spu的介绍 pms_spu_info_desc
            SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
            vo.setDesp(spuInfoDescEntity);
        }, executor);


        CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync((res) -> {
            // 5、获取spu的规格参数信息
            List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
            vo.setGroupAttrs(attrGroupVos);
        }, executor);

        CompletableFuture.allOf(infoFuture, imgFuture, saleAttrFuture, descFuture,baseAttrFuture).get();
        return vo;
    }

 

 

 

Guess you like

Origin blog.csdn.net/m0_62946761/article/details/132383085