Java线程池以及Future和CompletableFuture的用法
Java线程池以及Future和CompletableFuture的用法
是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。
为什么使用线程池?
频繁申请/销毁资源和调度资源,将带来额外的消耗,可能会非常巨大。
对资源无限申请缺少抑制手段,易引发系统资源耗尽的风险。
系统无法合理管理内部的资源分布,会降低系统的稳定性。
使用线程池的好处?
重用存在的线程,减少对象创建、消亡的开销。
有效的控制最大并发数,提高系统资源使用率。
统一的分配、调优和监控、可定时执行、定期执行。
线程池所在包java.
顶级接口Executor,真正的线程池接口是ExecutorService
Executors类提供创建线程池的方法
拒绝任务策略
1、AbortPolicy
当任务添加到线程池中被拒绝时,它将抛出RejectedExecutionException异常。(该策路下,直接丢弃任务,并抛出RejectedExecutionException异常)
2、DiscardPolicy
当任务添加到线程池中被拒绝时,默认情况下它将丢弃被拒绝的任务。(即该策略下,直接丢弃任务,什么都不做)
.DiscardoldestPolicy
当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。(该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列)
4、CallerRunsPolicy
不进入线程池执行,在这种方式(CallerRunsPolicy)中,任务将由调用者线程去执行。(用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务:如果执行程序已关闭,则会丢弃该任务。)
在Java多线程编程中,Future
是一个接口,用于表示一个异步计算的结果。当启动callable
线程时,就可以声明一个Future
,用于接收返回结果。它提供了一系列的方法,用于管理和获取任务的执行结果。Future
接口定义在java.
包中。
使用Future
可以将任务提交给线程池执行,并在需要时获取任务的执行结果。它的主要作用是允许主线程在提交异步任务后,继续执行其他操作,而不需要等待任务执行完成。
下面是Future
接口的一些常用方法:
boolean cancel(boolean mayInterruptIfRunning)
: 取消任务的执行。如果任务正在执行,并且mayInterruptIfRunning
参数设置为true
,则会尝试中断任务的执行。boolean isCancelled()
: 判断任务是否已被取消。boolean isDone()
: 判断任务是否已经完成。V get() throws InterruptedException, ExecutionException
: 获取任务的执行结果。如果任务还未执行完毕,get()
方法会阻塞直到任务执行完成。如果任务执行过程中发生异常,get()
方法会抛出ExecutionException
,可以通过getCause()
方法获取具体的异常信息。V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
: 在指定的时间内获取任务的执行结果,如果任务在指定时间内未执行完毕,会抛出TimeoutException
异常。
通过Future
接口,我们可以方便地提交任务并获取任务执行结果。这对于需要处理耗时操作的应用程序非常有用,可以提高系统的并发性和响应性。
栗子:四个刚需(线程)去买房摇号,future获取摇号结果。摇号结果未出,就一直阻塞。
public class FutureTest {/*** 买房摇号*/public static class Yaohao implements Callable<Integer> {/*** 返回摇号结果* @return 0:中签 1:没中* @throws Exception*/@Overridepublic Integer call() throws Exception {Random random = new Random();//模拟摇号,10天内出结果TimeUnit.SECODS.sleep((10));int result = (2);println( ().getame() is done!);return result;}}public static void main(String[] args) throws InterruptedException, ExecutionException {Yaohao gangxu1 = new Yaohao();Yaohao gangxu2 = new Yaohao();Yaohao gangxu = new Yaohao();Yaohao gangxu4 = new Yaohao();ExecutorService es = ();Future<Integer> result1 = es.submit(gangxu1);Future<Integer> result2 = es.submit(gangxu2);Future<Integer> result = es.submit(gangxu);Future<Integer> result4 = es.submit(gangxu4);es.shutdown();println(刚需1,摇号结果:(result1.get()==1?中签:没中));println(刚需2,摇号结果:(result2.get()==1?中签:没中));println(刚需,摇号结果:(result.get()==1?中签:没中));println(刚需4,摇号结果:(result4.get()==1?中签:没中));}}
两个栗子
public class FutureTest {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = (10);UserInfoService userInfoService = new UserInfoService();MedalService medalService = new MedalService();long userId =666L;long startTime = ();//调用用户服务获取用户基本信息FutureTask<UserInfo> userInfoFutureTask = new FutureTask<>(new Callable<UserInfo>() {@Overridepublic UserInfo call() throws Exception {return userInfoService.getUserInfo(userId);}});executorService.submit(userInfoFutureTask);Thread.sleep(00); //模拟主线程其它操作耗时FutureTask<MedalInfo> medalInfoFutureTask = new FutureTask<>(new Callable<MedalInfo>() {@Overridepublic MedalInfo call() throws Exception {return medalService.getMedalInfo(userId);}});executorService.submit(medalInfoFutureTask);UserInfo userInfo = userInfoFutureTask.get();//获取个人信息结果MedalInfo medalInfo = medalInfoFutureTask.get();//获取勋章信息结果println(总共用时 (() - startTime) ms);}
}
FutureTask
和Future
的区别
-
功能不同:
Future
是一个接口,用于表示一个异步计算的结果,可以用来取消任务、查询结果是否完成以及获取计算结果。FutureTask
是一个实现了Future
接口的具体类,同时也是一个可执行的任务,可以被Executor
执行。 -
使用方式不同:
Future
通常与ExecutorService
一起使用,用来提交任务并获取任务的执行结果。FutureTask
既可以直接使用FutureTask
对象来提交任务,也可以将其作为Runnable
或Callable
对象提交给ExecutorService
。 -
创建方式不同:创建
Future
对象时,通常使用ExecutorService
提交任务后返回的Future
实例。而创建FutureTask
对象时,可以直接通过new FutureTask(callable)
构造函数或new FutureTask(runnable, result)
构造函数来实例化。 -
取消任务的能力不同:
Future
接口提供了cancel(boolean mayInterruptIfRunning)
方法,用于取消任务的执行。而FutureTask
类还提供了cancel(boolean mayInterruptIfRunning)
方法以及boolean cancel(boolean mayInterruptIfRunning)
方法,用于取消任务的执行并返回取消成功与否的信息。
总的来说,Future
是一个接口,用于表示一个异步计算的结果;FutureTask
是Future
接口的具体实现类,同时也是一个可执行的任务。FutureTask
相比Future
更为灵活,能够直接作为任务提交给ExecutorService
执行,并提供了更多的取消任务的方法。
ExecutorService 的submit方法的作用
ExecutorService
是 Java 提供的一个用于管理线程池的接口。它可以用来执行异步任务并管理线程的生命周期。submit
方法是 ExecutorService
接口定义的一个方法,用于向线程池提交一个任务并获取一个 Future
对象来表示任务的执行结果。
具体来说,submit
方法用于提交一个 Callable
或 Runnable
对象到线程池中执行。Callable
是带有返回结果的任务,而 Runnable
是没有返回结果的任务。submit
方法将任务提交给线程池后会立即返回一个 Future
对象,通过这个对象可以获得任务的执行结果或者取消任务的执行。
使用 submit
方法可以方便地管理线程池中的任务,可以通过 Future
对象获取任务的状态、结果或者取消任务的执行。通常情况下,我们可以使用 submit
方法来替代 execute
方法,因为它具有更多的功能和灵活性。
submit 和execute 的区别
submit()
和 execute()
是 ExecutorService
接口用于提交任务到线程池的两种方法,它们之间有以下区别:
-
返回值类型不同:
submit()
方法返回一个Future
对象,可以用来获取任务的执行结果或者取消任务的执行;而execute()
方法没有返回值,无法获取任务的执行结果。 -
异常处理不同:
submit()
方法能够捕获任务执行过程中抛出的异常,将异常封装到Future
对象中,通过调用get()
方法或者get(long, TimeUnit)
方法获取任务的执行结果时,如果任务抛出了异常,可以通过ExecutionException
来获取异常信息;而execute()
方法无法对任务抛出的异常进行处理,如果任务抛出了异常,线程池会将异常记录到控制台。 -
参数类型不同:
submit()
方法接受Callable
或者Runnable
对象作为参数,Callable
是带有返回值的任务,而Runnable
是没有返回值的任务;而execute()
方法只接受Runnable
对象作为参数。因此,如果需要获取任务执行的结果,应该使用submit()
方法,如果不需要获取结果,可以使用execute()
方法。
总的来说,submit()
方法比 execute()
方法更加灵活,可以获取任务的执行结果和捕获任务中抛出的异常,因此在处理需要获取结果或者处理异常的任务时,推荐使用 submit()
方法。而对于不需要获取结果的简单任务,可以使用 execute()
方法。
Future的局限
Future对于结果的获取,不是很友好,只能通过阻塞或者轮询的方式得到任务的结果。
Future.get() 就是阻塞调用,在线程获取结果之前get方法会一直阻塞。Future提供了一个isDone方法,可以在程序中轮询这个方法查询执行结果。
阻塞的方式和异步编程的设计理念相违背,而轮询的方式会耗费无谓的CPU资源。因此,JDK8设计出CompletableFuture,提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。
CompletableFuture 使用详解
CompletableFuture 使用详解
CompletableFuture使用详解
异步编程利器:CompletableFuture详解 |Java 开发实战
CompletableFuture提供了多种方法来获取异步计算的结果。以下是一些常用的方法:
- 使用get()方法:CompletableFuture类继承了Future接口,因此可以使用get()方法来获取计算的结果。但需要注意的是,get()方法是阻塞的,会等待异步计算完成后返回结果。如果计算没有完成,get()方法会一直阻塞,直到计算完成并返回结果或者抛出异常。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> Hello);
String result = future.get(); // 阻塞获取计算结果
- 使用join()方法:与get()方法类似,join()方法也可以获取计算结果,但它是非阻塞的。如果计算没有完成,join()方法会等待计算完成后立即返回结果。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> Hello);
String result = future.join(); // 非阻塞获取计算结果
- 使用CompletableFuture组合方法:CompletableFuture提供了一系列方法,如thenApply、thenAccept、thenCompose等,用于对计算结果进行处理。这些方法返回的是新的CompletableFuture实例,可以继续链式调用。通过这些方法,我们可以在异步计算完成后,对结果进行进一步的操作或处理。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> Hello).thenApply(s -> s World).thenApply(String::toUpperCase);
String result = future.get();
- 使用回调方法:CompletableFuture还提供了一系列回调方法,如whenComplete、handle、thenAccept、exceptionally等,用于在计算完成后执行相应的操作或处理。这些方法允许我们以非阻塞的方式处理计算结果,并在计算完成或出现异常时执行相应的逻辑。
CompletableFuture.supplyAsync(() -> Hello).thenApply(s -> s World).thenAccept(::println).exceptionally(ex -> {println(Error: ex.getMessage());return null;});
上述是一些常用的获取CompletableFuture计算结果的方法,根据具体需求和场景,你可以选择适合的方式来处理异步计算的结果。
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
上一篇:Cloud任务
下一篇:法币将成为公共区块链的必要条件
推荐阅读
留言与评论(共有 12 条评论) |
本站网友 氨气的危害 | 20分钟前 发表 |
ExecutionException {Yaohao gangxu1 = new Yaohao();Yaohao gangxu2 = new Yaohao();Yaohao gangxu = new Yaohao();Yaohao gangxu4 = new Yaohao();ExecutorService es = ();Future<Integer> result1 = es.submit(gangxu1);Future<Integer> result2 = es.submit(gangxu2);Future<Integer> result = es.submit(gangxu);Future<Integer> result4 = es.submit(gangxu4);es.shutdown();println(刚需1,摇号结果:(result1.get()==1?中签 | |
本站网友 残阳如血 | 24分钟前 发表 |
有效的控制最大并发数,提高系统资源使用率 | |
本站网友 上海电信提速 | 5分钟前 发表 |
DiscardPolicy 当任务添加到线程池中被拒绝时,默认情况下它将丢弃被拒绝的任务 | |
本站网友 喜马拉雅中心 | 23分钟前 发表 |
但需要注意的是,get()方法是阻塞的,会等待异步计算完成后返回结果 | |
本站网友 滑铁卢 | 25分钟前 发表 |
Future接口定义在java.包中 | |
本站网友 新疆亚心网 | 5分钟前 发表 |
(用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务:如果执行程序已关闭,则会丢弃该任务 | |
本站网友 海安租房 | 19分钟前 发表 |
没中));println(刚需4,摇号结果:(result4.get()==1?中签 | |
本站网友 东北三省旅游景点 | 13分钟前 发表 |
使用Future可以将任务提交给线程池执行,并在需要时获取任务的执行结果 | |
本站网友 唐小僧理财 | 29分钟前 发表 |
有效的控制最大并发数,提高系统资源使用率 | |
本站网友 南朗二手房 | 12分钟前 发表 |
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> Hello).thenApply(s -> s World).thenApply(String | |
本站网友 物美超市官网 | 11分钟前 发表 |
DiscardPolicy 当任务添加到线程池中被拒绝时,默认情况下它将丢弃被拒绝的任务 |