并发编程之Executor框架

Executor框架、Executors、ExecutorService及CompletionService
Executor:java.util.concurrent提供了一种灵活的线程池 实现作为Executor的一部分。Executor虽是个简单的接口,但能支持多种不同类型的任务执行策略。

public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

Executor:一个接口,只有一个executor方法,该方法接收一个Runable实例,它用来执行一个任务,任务即一个实现了Runnable接口的类,一般来说,Runnable任务开辟在新线程中的使用方法为:new Thread(new RunnableTask())).start(),但在Executor中,可以使用Executor而不用显示地创建线程:executor.execute(new RunnableTask()); // 异步执行

ExecutorService:是一个比Executor使用更广泛的子类接口,其提供了生命周期管理的方法(ExecutorService的生命周期三个状态:运行、关闭、终止),返回 Future 对象,以及可跟踪一个或多个异步任务执行状况返回Future的方法;可以调用shutdown()方法来平滑地关闭 ExecutorService,调用该方法后,将导致ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService。shutdownNow方法将执行粗暴的关闭过程:将尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。因此我们一般用该接口来实现和管理多线程。
ExecutorService.submit() 方法返回的 Future 对象,可以调用isDone()方法查询Future是否已经完成。当任务完成时,它具有一个结果,你可以调用get()方法来获取该结果。你也可以不用isDone()进行检查就直接调用get()获取结果,在这种情况下,get()将阻塞,直至结果准备就绪,还可以取消任务的执行。Future 提供了 cancel() 方法用来取消执行 pending 中的任务。

public interface ExecutorService extends Executor {
	//生命周期管理方法
	void shutdown();
	List<Runnbale> shutdownNow();
	boolean isShutdown();
	boolean isTerminated();
	boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
	//其他部分方法
	<T> Future<T> submit(Callable<T> task);
	<T> Future<T> submit(Runnable task, T result);
	<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException;
}

Executors:提供线程池的操作。通过调用Executos中的静态工厂方法之一来创建一个线程池:
newFixedThreadPool:将创建一个固定长度的线程池,每当提交一个任务时就创建一个线程,直到达到线程池的最大数量,这是线程池的规模将不再变化(如果某个线程由于发生了未预期的Exception而结束,那么线程池会补充一个新的线程)。
newCachedThreadPool:将创建一个可缓存的线程池,如果线程池的当前规模超过了处理需求时,那么将回收空闲的线程,而当需求增加时,则可以添加新的线程,线程池的规模不存在任何限制。
newSingleThreadExecutor:一个单线程的Executor,它创建单个工作者线程来执行任务,如果这个线程异常结束,会创建另一个线程来替代。newSingleThreadExecutor能确保依照任务在队列中的顺序来串行执行。
newScheduledThreadPool:创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

Executor 和 ExecutorService 主要的区别:
1.ExecutorService 接口继承了 Executor 接口,是 Executor 的子接口
2.Executor 接口定义了 execute()方法用来接收一个Runnable接口的对象,而 ExecutorService 接口中的 submit()方法可以接受Runnable和Callable接口的对象。
3. Executor 中的 execute() 方法不返回任何结果,而 ExecutorService 中的 submit()方法可以通过一个 Future 对象返回运算结果。
4.除了允许客户端提交一个任务,ExecutorService 还提供用来控制线程池的方法。比如:调用 shutDown() 方法终止线程池。

CompletionService:异步非阻塞获取并行任务执行结果。CompletionService将Executor(异步线程)和BlockingQueue(队列)的功能融合在一起,可以将Callable任务提交给它来执行,然后使用类似于队列操作的take和poll等方法来获得已完成的结果。通过该类可以立即获取每个线程的结果。

	//初始化线程池
    ExecutorService threadPool = Executors.newFixedThreadPool(10);
    //创建线程
    CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool);
    for (int j = 1; j <= 5; j++) {

        final int index = j;
        completionService.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                //第三个线程睡眠等待
                if (index == 3) {
                    java.lang.Thread.sleep(3000l);
                }
                return index;
            }
        });
    }
    threadPool.shutdown();

    for (int i = 0; i < 5; i++) {
        try {
            System.out.println("线程:"+completionService.take().get()+" 任务执行结束:");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

获取的结果是无序的,第三个睡眠线程始终最后结束,也证实了获取结果的方式是非阻塞的。如下:
线程:2 任务执行结束
线程:1 任务执行结束
线程:5 任务执行结束
线程:4 任务执行结束
线程:3 任务执行结束

文章参考:
https://blog.csdn.net/weixin_40304387/article/details/80508236
https://blog.csdn.net/woshilijiuyi/article/details/78970497

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值