三.多线程JUC篇-3.17 ExecutorService API详细讲解

1.shutdown

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
        isShutDown();
    }

    private static void isShutDown() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        System.out.println(executorService.isShutdown());
        executorService.shutdown();
        System.out.println(executorService.isShutdown());
        executorService.execute(() -> System.out.println("I will be executed after shutDown ???"));
    }
}

//输出:
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.wangwenjun.concurrent.executors.ExecutorServiceExample1$$Lambda$2/558638686@448139f0 rejected from java.util.concurrent.ThreadPoolExecutor@7cca494b[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:668)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.isShutDown(ExecutorServiceExample1.java:28)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.main(ExecutorServiceExample1.java:9)
false
true

2.terminate

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
       isTerminated();
    }

    private static void isTerminated() {
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        executorService.shutdown();
        System.out.println(executorService.isShutdown());
        System.out.println(executorService.isTerminated());
        System.out.println(((ThreadPoolExecutor)executorService).isTerminating());
    }
}
//输出:在这里插入代码片 
true
false
true

3.捕获异常

3.1 setUncaughtExceptionHandler

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
        executeRunnableError();
    }

    private static void executeRunnableError() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());
        IntStream.range(0, 10).boxed().forEach(i -> executorService.execute(() -> System.out.println(1 / 0)));
        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.MINUTES);
        System.out.println("=====================================");
    }

    private static class MyThreadFactory implements ThreadFactory {
        private final static AtomicInteger SEQ = new AtomicInteger();

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("My-Thread-" + SEQ.getAndIncrement());
            t.setUncaughtExceptionHandler((i, cause) -> {
                System.out.println("The thread " + i.getName() + " execute failed.");
               // cause.printStackTrace();
                System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
            });
            return t;
        }

    }
}

//输出
=====================================
The thread My-Thread-1 execute failed.
The thread My-Thread-0 execute failed.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

3.2 线程内部分步骤

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
        executeRunnableTask();
    }

    /*
     * <pre>
     *                               |--->操作1
     *                               |--->操作2
     * send request-->store db-->10->|--->操作3-->给出不同的反馈
     *                                  |--->操作4
     *                                  |--->操作5
     * </pre>
     */
    private static void executeRunnableTask() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        IntStream.range(0, 2).boxed().forEach(i -> executorService.execute(
                new MyTask(i) {

                    @Override
                    protected void error(Throwable cause) {
                        System.out.println("The no:" + i + " failed , update status to ERROR.");
                    }

                    @Override
                    protected void done() {
                        System.out.println("The no:" + i + " successfully , update status to DONE.");
                    }

                    @Override
                    protected void doInit() {
                        //do nothing
                    }

                    @Override
                    protected void doExecute() {
                        if(i % 3 == 0) {
                            int tmp = 1 / 0;
                        }
                    }
                }
        ));
        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.MINUTES);
        System.out.println("=====================================");
    }

    private static class MyThreadFactory implements ThreadFactory {
        private final static AtomicInteger SEQ = new AtomicInteger();

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("My-Thread-" + SEQ.getAndIncrement());
            t.setUncaughtExceptionHandler((i, cause) -> {
                System.out.println("The thread " + i.getName() + " execute failed.");
                cause.printStackTrace();
                System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
            });
            return t;
        }

    }

    private abstract static class MyTask implements Runnable {
        protected final int no;

        public MyTask(int no) {
            this.no = no;
        }

        @Override
        public void run() {
            try {
                this.doInit();
                this.doExecute();
                this.done();
            } catch (Throwable cause) {
                this.error(cause);
            }
        }

        protected abstract void error(Throwable cause);

        protected abstract void done();

        protected abstract void doExecute();

        protected abstract void doInit();
    }
}

//输出:
The no:1 successfully , update status to DONE.
The no:0 failed , update status to ERROR.
=====================================

4.拒绝策略

4.1 线程池大小足够

public class ExecutorServiceExample1 {
    public static void main(String[] args) {

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 3, 10, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<Runnable>(1));
        for (int i = 0; i < 4; i++) {
            MyTask myTask = new MyTask(i);
            executor.execute(myTask);
            System.out.println("线程池中线程数目:" + executor.getPoolSize() + ",队列中等待执行的任务数目:" +
                    executor.getQueue().size() + ",已执行完的任务数目:" + executor.getCompletedTaskCount());
        }
        executor.shutdown();
    }
}

class MyTask implements Runnable {
    private int taskNum;

    public MyTask(int num) {
        this.taskNum = num;
    }

    @Override
    public void run() {
        System.out.println("线程名称:" + Thread.currentThread().getName() + ",正在执行task " + taskNum);
        try {
            Thread.currentThread().sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("task " + taskNum + "执行完毕");

    }
}

//输出:
线程池中线程数目:1,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程名称:pool-1-thread-1,正在执行task 0
线程池中线程数目:2,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程池中线程数目:3,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程名称:pool-1-thread-2,正在执行task 1
线程名称:pool-1-thread-3,正在执行task 3
task 0执行完毕
线程名称:pool-1-thread-1,正在执行task 2
task 1执行完毕
task 3执行完毕
task 2执行完毕

Process finished with exit code 0

4.2 AbortPolicy

//将任务数调整为5
//超过的任务(在这里有一个任务)会被拒绝,并抛出任何异常
线程池中线程数目:1,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程池中线程数目:3,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程名称:pool-1-thread-1,正在执行task 0
线程名称:pool-1-thread-2,正在执行task 1
线程名称:pool-1-thread-3,正在执行task 3
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.wangwenjun.concurrent.executors.MyTask@135fbaa4 rejected from java.util.concurrent.ThreadPoolExecutor@45ee12a7[Running, pool size = 3, active threads = 3, queued tasks = 1, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.main(ExecutorServiceExample1.java:14)
task 0执行完毕
线程名称:pool-1-thread-1,正在执行task 2
task 3执行完毕
task 1执行完毕
task 2执行完毕

4.3 DiscardPolicy

//超过的任务(在这里有一个任务)会被拒绝,但不会抛出任何异常
线程池中线程数目:1,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程池中线程数目:3,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程池中线程数目:3,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程名称:pool-1-thread-2,正在执行task 1
线程名称:pool-1-thread-1,正在执行task 0
线程名称:pool-1-thread-3,正在执行task 3
task 1执行完毕
task 0执行完毕
task 3执行完毕
线程名称:pool-1-thread-2,正在执行task 2
task 2执行完毕

4.4 DiscardOldestPolicy

当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。

4.4 CallerRunsPolicy

//由调用线程执行,而不是ThreadPoolExecute
线程池中线程数目:1,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:0,已执行完的任务数目:0
线程池中线程数目:2,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程池中线程数目:3,队列中等待执行的任务数目:1,已执行完的任务数目:0
线程名称:main,正在执行task 4
线程名称:pool-1-thread-1,正在执行task 0
线程名称:pool-1-thread-2,正在执行task 1
线程名称:pool-1-thread-3,正在执行task 3
task 4执行完毕
task 1执行完毕
task 0执行完毕
线程名称:pool-1-thread-2,正在执行task 2
task 3执行完毕
线程池中线程数目:3,队列中等待执行的任务数目:1,已执行完的任务数目:0
task 2执行完毕

5. ActiveCount

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
        test();
    }

    private static void test() throws InterruptedException {
        ThreadPoolExecutor executorService = (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
        System.out.println(executorService.getActiveCount());

        executorService.execute(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        TimeUnit.MILLISECONDS.sleep(20);
        System.out.println(executorService.getActiveCount());

    }
}

//输出
0
1

5. AllowCoreThreadTimeOut

//如果不设置allowCoreThread,pool会一直存在,因为core threads一直为5
//如果设置了allowCoreThread,等到3秒会,pool会停止
private static void testAllowCoreThreadTimeOut() {
        ThreadPoolExecutor executorService = (ThreadPoolExecutor)Executors.newFixedThreadPool(5);
        executorService.setKeepAliveTime(3, TimeUnit.SECONDS); 
        executorService.allowCoreThreadTimeOut(true); //为true时keepAliveTime的时间必须大于0
        IntStream.range(0, 5).boxed().forEach(i -> {
            executorService.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        });
    }

6.remove

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
        testRemove();
    }

    private static void testRemove() throws InterruptedException {
        ThreadPoolExecutor executorService = (ThreadPoolExecutor)Executors.newFixedThreadPool(2);
        executorService.setKeepAliveTime(10, TimeUnit.SECONDS);
        //为true时keepAliveTime的时间必须大于1
        executorService.allowCoreThreadTimeOut(true);
        IntStream.range(0, 2).boxed().forEach(i -> {
            executorService.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(5);
                    System.out.println("================ I am finished.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        });

        TimeUnit.MILLISECONDS.sleep(20);
        Runnable r = () -> {
            System.out.println("I will never be executed.");
        };
        executorService.execute(r);
        TimeUnit.MILLISECONDS.sleep(20);
        //将queue中的任务删除
        executorService.remove(r);
    }
}

//输出:
================ I am finished.
================ I am finished.

7.beforeExecute和afterExecute

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException {
        testThreadPoolAdvice();
    }



    //beforeExecute和afterExecute类似于切面
    private static void testThreadPoolAdvice() {
        ThreadPoolExecutor executorService = new MyThreadPoolExecutor(1, 2, 30, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), r -> {
            Thread t = new Thread(r);
            return t;
        }, new ThreadPoolExecutor.AbortPolicy());

        executorService.execute(new MyRunnable(1) {
            @Override
            public void run() {
                System.out.println("=================" + 1/0);
            }
        });
    }

    private abstract static class MyRunnable implements Runnable {
        private final int no;

        public MyRunnable(int no) {
            this.no = no;
        }

        protected int getData() {
            return this.no;
        }
    }

    private static class MyThreadPoolExecutor extends ThreadPoolExecutor {

        public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
                                    BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        }

        @Override
        protected void beforeExecute(Thread t, Runnable r) {
            System.out.println("init the " + ((MyRunnable)r).getData());
        }

        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            if(null == t) {
                System.out.println("successful " + ((MyRunnable)r).getData());
            } else {
                System.out.println("failed " + t.getMessage());
            }
        }
    }
}

//输出
init the 1
failed / by zero
Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1$1.run(ExecutorServiceExample1.java:27)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:748)

8.invoke和submit

8.1 InvokeAny

//InvokeAny会阻塞主线程,直到某一线程执行完毕
//InvokeAny有一个线程执行完毕,其它线程会取消执行,不在执行
//InvokeAny有一个线程执行完毕,如果其它线程同时执行完毕,就不存在取消一说了
public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        testInvokeAny();
    }



    private static void testInvokeAny() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        List<Callable<Integer>> callableList = IntStream.range(0, 5).boxed().map(
                i -> (Callable<Integer>) () -> {
                    System.out.println(Thread.currentThread().getName() + " :" + i + " start");
                    TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(20));
                    System.out.println(Thread.currentThread().getName() + " :" + i + " end");
                    return i;
                }
        ).collect(Collectors.toList());
        //这是一个同步方法,执行完成后才会执行后面的任务
        Integer value = executorService.invokeAny(callableList);
        System.out.println("===================finished=====================");
        System.out.println(value);
    }
}

//输出:
pool-1-thread-1 :0 start
pool-1-thread-3 :2 start
pool-1-thread-2 :1 start
pool-1-thread-5 :4 start
pool-1-thread-4 :3 start
pool-1-thread-2 :1 end
===================finished=====================
1

8.2 InvokeAny timeout

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        testInvokeAnyTimeOut();
    }



    private static void testInvokeAnyTimeOut() throws InterruptedException, ExecutionException, TimeoutException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        List<Callable<Integer>> callableList = IntStream.range(0, 5).boxed().map(
                i -> (Callable<Integer>) () -> {
                    System.out.println(Thread.currentThread().getName() + " :" + i + " start");
                    TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(100));
                    System.out.println(Thread.currentThread().getName() + " :" + i + " end");
                    return i;
                }
        ).collect(Collectors.toList());
        //这是一个同步方法,执行完成后才会执行后面的任务
        Integer value = executorService.invokeAny(callableList, 3, TimeUnit.SECONDS);
        System.out.println("===================finished=====================");
        System.out.println(value);
    }
}

//输出
pool-1-thread-1 :0 start
pool-1-thread-4 :3 start
pool-1-thread-3 :2 start
pool-1-thread-2 :1 start
pool-1-thread-5 :4 start
Exception in thread "main" java.util.concurrent.TimeoutException
	at java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:184)
	at java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:225)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.testInvokeAnyTimeOut(ExecutorServiceExample1.java:30)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.main(ExecutorServiceExample1.java:13)

8.3 InvokeAll

//InvokeAll同样是个阻塞方法
//这里发现一个问题,就是callabe执行完后,才进行foreach,这里在jdk1.9已解决或者rxjava框架
public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        testInvokeAll();
    }



    private static void testInvokeAll() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        //这是一个同步方法,执行完成后才会执行后面的任务
        executorService.invokeAll(
                IntStream.range(0, 5).boxed().map(
                        i -> (Callable<Integer>) () -> {
                            TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(30));
                            System.out.println(Thread.currentThread().getName() + " :" + i);
                            return i;
                        }
                ).collect(Collectors.toList())
        ).stream().map(future -> {
            try {
                return future.get();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }).forEach(System.out::println);

        System.out.println("===================finished=====================");
    }
}

//输出:
pool-1-thread-1 :0
pool-1-thread-5 :4
pool-1-thread-3 :2
pool-1-thread-4 :3
pool-1-thread-2 :1
0
1
2
3
4
===================finished=====================

8.5 submit

public class ExecutorServiceExample1 {
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        testSubmitRunnable();
        testSubmitRunnableWithResult();
    }



    /**
     * {@link ExecutorService#submit(Runnable)}
     */
    private static void testSubmitRunnable() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Future<?> future = executorService.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        //get()会产生阻塞,等待前面的任务执行完
        Object NULL = future.get();
        System.out.println("R:" + NULL);
    }

    /**
     * {@link ExecutorService#submit(Runnable, Object)}
     */
    private static void testSubmitRunnableWithResult() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        String result = "DONE";
        Future<String> future = executorService.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, result);
        result = future.get();
        System.out.println("R:" + result);
    }
}

//输出
pool-1-thread-1
R:null

pool-2-thread-1
R:DONE
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值