ExecutorService等待线程执行并设置超时时间的三种方式

目录

前言

1、使用Future.get()

2、使用CountDownLatch.await()

3、使用ExecutorService.awaitTermination()


前言

日常开发中肯定会遇到需要同步执行的线程,即主线程需要等待子线程执行完毕才能继续接下来的操作,并且线程需要在特定的时间内执行完成,例如脚本执行这一类,这时我们就可以使用ExecutorService线程池来完成我们的需求,我了解了下大致有三种方式

1、使用Future.get()

Future简单来说就是对具体的Runnable和Callable任务执行结果进行任务取消、任务查询、获取结果的一个东西,由名字也得得出其应该是指向结果的连接,当获得该对象的时候,其时间上任务并未完成,这也就是它可能被称为Future的一个原因把。所以我们需要调用Future.get()方法来强制获取结果,同时设置超时时间,一旦超时,我们便手动取消该任务,代码例子见如下:

    @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、使用CountDownLatch.await()

该同步辅助类旨在在完成一组正在执行操作的线程之前,允许一个或多个线程一直等待,即同步等待,该方法在完成上述需求时需要事先知道有多少线程数,因为其本身就是类似于一个计数器,最开始需要初始化指定数量的线程,每完成一个,计数器减1,只要计数器的值大于0,则主线程一直阻塞,注意在调用该类的await阻塞等待时最好设置超时时间,否则容易造成死锁,下面看下简单代码实现:

@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()

该方法会一直等待所有的任务都结束或超时时间到则立即结束,若所有任务都执行成功则返回true,否则返回false,需要注意的是在最后需关闭当前线程池或手动取消仍在执行的任务,由于需要关闭线程池,所以除非是一次性任务处理事件,否则若是需要重复使用当前线程池,则每次执行时都会重复创建和执行线程池,不是你的最佳选择,看下简单实现:

    @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();
        }

    }

猜你喜欢

转载自blog.csdn.net/m0_38001814/article/details/102730198
今日推荐