java 多线程执行不同的运算_JAVA笔记_多线程_异步计算

一、 Callable,Future,FutureTask

Callable接口与Runnable接口类似,封装了一个异步运行的任务,但与run方法不同,它的call方法可以有一个返回值并且可以抛出异常。Callable接口是个参数化的类型 public interface Callable{ V call() throws Exception} ,类型参数就是返回值的类型。

Future接口用于表示异步计算的结果,并提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用get方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由cancel方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用Future但又不提供可用的结果,则可以声明Future>形式类型、并返回null作为底层任务的结果。下面是JDK给的例子:

interface ArchiveSearcher { String search(String target); }

class App {

ExecutorService executor = ...

ArchiveSearcher searcher = ...

void showSearch(final String target)throws InterruptedException {

Futurefuture = executor.submit(new Callable() {

public String call() {

return searcher.search(target);

}});

displayOtherThings(); // do other things while searching

try {

displayText(future.get()); // use future

} catch (ExecutionException ex) { cleanup(); return; }

}

}

FutureTask类代表可取消的异步计算,它采用包装器机制,可将Callable转换成Runnable和Future,它同时实现了这两个接口。下面是用法实例:

CallablemyCallable = new MyCallable();

FutureTask task = new FutureTask(myCallable);

new Thread(task).start();

...

T result = task.get();

二、执行器

1.Executor接口与ThreadPoolExecutor

Executor用于执行已提交的Runnable任务,它将任务的提交与每个任务如何运行的机制(包括线程使用的细节、调度等)分离开来。它仅提供了一个excecute方法。它有两个子接口:ExcecuteService和SheduledExecutorService

ExecutorService提供了相关方法以管理终止,以及相关方法以跟踪一个或多个异步任务执行状况。可以关闭ExecutorService,shutdown方法被调用后将等待已提交的任务运行结束才会关闭服务,而shutdownNow方法将阻止任务启动并尝试停止正在运行的任务。被关闭的ExecutorService没有等待启动的任务,没有正在运行的任务,也无法向其提交新的任务。应该关闭不再使用的ExecutorService以回收资源。

ThreadPoolExecutor线程池实现了ExecutorService接口。使用线程池可以避免频繁创建线程的开销,适合执行大量生命周期较短的任务。对于每个任务,如果线程池中有线程可用,则让它立即执行任务,否则创建一个新线程让其执行或者将其放入等待队列。

线程池的常见用法:

(1)调用Executors中的静态方法或者ThreadPoolExecutor构造方法创建线程池对象。

(2)调用submit提交Runnable或Callable对象,

(3)如果要取消一个任务,那就应该保存好返回的Future对象。

(4)当不再提交任何任务时,应该调用shutdown方法关闭线程池

2. 控制任务组

ExecutorService执行器提供了许多控制任务执行的方法。

shutdownNow方法可以取消所有正在执行的任务和未执行的任务。

invokeAny方法将所有所有任务对象作为一个集合提交到执行器中,并返回一个Future列表。当这些任务中的任一个执行完毕后返回结果,无法知道返回的究竟是哪个任务的结果。此方法适合于多种方式并行处理一个问题的场景,只要求尽快得到结果,具体哪种方法起作用不关心。

invokeAll与invokeAny不同,所有任务都会返回结果。但如果Future列表中第一个对应任务执行时间最长,则其他任务结果的获得不得不等待。可以使用ExecutorCompletionService来获取顺序返回的任务结果。

ExecutorCompletionService的用法:

ExecutorCompletionService service = newExecutorCompletionService(executor);

for(Callabletask : tasks)

service.submit(task);

for(int i=0;i

processFurther(service.take().get());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值