Three ways for ExecutorService to wait for the thread to execute and set the timeout period

table of Contents

Preface

1. Use Future.get()

2. Use CountDownLatch.await()

3、使用ExecutorService.awaitTermination()


Preface

In daily development, you will definitely encounter threads that need to be executed synchronously, that is, the main thread needs to wait for the execution of the child thread to complete the next operation, and the thread needs to be executed within a specific time, such as script execution, then we We can use the ExecutorService thread pool to complete our needs. I understand that there are roughly three ways

1. Use Future.get()

In simple terms, Future is a thing that performs task cancellation, task query, and obtaining results for specific Runnable and Callable task execution results. It should also be derived from the name. It should be a connection to the result. When the object is obtained, its time The above task has not been completed, which is one reason why it may be called Future. So we need to call the Future.get() method to force the result to be obtained, and at the same time set the timeout period. Once the timeout expires, we will manually cancel the task. The code example is as follows:

    @Test
    public void test09() {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // 采用Future
        Future<Boolean> future = executorService.submit(() -> {
            Thread.sleep(3000);
            System.out.println("线程执行完成");
            return true;
        });

        try {
            if (future.get(4, TimeUnit.SECONDS)) {
                System.out.println("任务执行成功");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            System.out.println("执行超时");
            future.cancel(true);
        }
    }

2. Use CountDownLatch.await()

The synchronization auxiliary class is designed to allow one or more threads to wait until the completion of a set of threads that are performing operations, that is, synchronous waiting. This method needs to know how many threads there are in advance when completing the above requirements, because it is similar in itself For a counter, a specified number of threads need to be initialized at the beginning. Each time one is completed, the counter is decremented. As long as the value of the counter is greater than 0, the main thread has been blocked. Note that it is best to set a timeout when calling this type of await blocking waiting. Otherwise, it is easy to cause deadlock. Let's take a look at the simple code implementation:

@Test
    public void test09() {
        ExecutorService executorService = Executors.newFixedThreadPool(100);

        CountDownLatch countDownLatch = new CountDownLatch(1);
        executorService.execute(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("线程执行完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                countDownLatch.countDown();
            }
        });
        try {
            if (countDownLatch.await(4, TimeUnit.SECONDS)) {
                System.out.println("任务执行成功");
            } else {
                System.out.println("执行超时");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

3、使用ExecutorService.awaitTermination()

This method will always wait for the end of all tasks or the timeout period to end immediately. If all tasks are executed successfully, it will return true, otherwise it will return false. It should be noted that the current thread pool needs to be closed or manually cancelled at the end. Task, because the thread pool needs to be closed, unless it is a one-time task to process events, if the current thread pool needs to be reused, the thread pool will be created and executed repeatedly every time it is executed. This is not your best choice. Look at the simple implementation :

    @Test
    public void test09() {
        ExecutorService executorService = Executors.newFixedThreadPool(100);

        executorService.execute(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("线程执行完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        try {
            if (executorService.awaitTermination(2, TimeUnit.SECONDS)) {
                System.out.println("主线程开始执行");
            } else {
                System.out.println("执行超时");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
        }

    }

 

Guess you like

Origin blog.csdn.net/m0_38001814/article/details/102730198