23.FutureTask基本操作总结

1.FutureTask简介

在Executors框架体系中,FutureTask用来表示可获取结果的异步任务。FutureTask实现了Future接口,FutureTask提供了启动和取消异步任务,查询异步任务是否计算结束以及获取最终的异步任务的结果的一些常用的方法。通过get()方法来获取异步任务的结果,但是会阻塞当前线程直至异步任务执行结束。一旦任务执行结束,任务不能重新启动或取消,除非调用runAndReset()方法。在FutureTask的源码中为其定义了这些状态:

private static final int NEW          = 0;
private static final int COMPLETING   = 1;
private static final int NORMAL       = 2;
private static final int EXCEPTIONAL  = 3;
private static final int CANCELLED    = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED  = 6;

另外,在《java并发编程的艺术》一书,作者根据FutureTask.run()方法的执行的时机,FutureTask分为了3种状态:

 

  1. 未启动。FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态。当创建一个FutureTask,还没有执行FutureTask.run()方法之前,FutureTask处于未启动状态。

  2. 已启动。FutureTask.run()方法被执行的过程中,FutureTask处于已启动状态。

  3. 已完成。FutureTask.run()方法执行结束,或者调用FutureTask.cancel(...)方法取消任务,或者在执行任务期间抛出异常,这些情况都称之为FutureTask的已完成状态。

下图总结了FutureTask的状态变化的过程:

由于FutureTask具有这三种状态,因此执行FutureTask的get方法和cancel方法,当前处于不同的状态对应的结果也是大不相同。这里对get()和cancel()做个总结:

get方法

当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞。如果FutureTask处于已完成状态,调用FutureTask.get()方法将导致调用线程立即返回结果或者抛出异常

cancel方法

当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将此任务永远不会执行;

当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断线程的方式来阻止任务继续进行,如果执行FutureTask.cancel(false)将不会对正在执行任务的线程有任何影响;

FutureTask处于已完成状态时,执行FutureTask.cancel(...)方法将返回false。

对Future的get()方法和cancel()方法用下图进行总结

2. FutureTask的基本使用

FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给Executor执行,也可以由调用的线程直接执行(FutureTask.run())。另外,FutureTask的获取也可以通过ExecutorService.submit()方法返回一个FutureTask对象,然后在通过FutureTask.get()或者FutureTask.cancel()方法。

应用场景:当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,此时可以使用FutureTask。假设有多个线程执行若干任务,每个任务最多只能被执行一次。当多个线程试图执行同一个任务时,只允许一个线程执行任务,其他线程需要等待这个任务执行完后才能继续执行。

参考文献

《java并发编程的艺术》

转载于:https://www.cnblogs.com/itxiaok/p/10356598.html

09-Sep-2025 17:23:26.604 严重 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.startup.HostConfig.deployWARs 等待WAR文件的多线程部署完成时出错 java.lang.InterruptedException at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:404) at java.util.concurrent.FutureTask.get(FutureTask.java:191) at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:762) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:426) at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1612) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:304) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1159) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1381) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1385) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1353) at java.lang.Thread.run(Thread.java:748) 09-Sep-2025 17:23:35.778 警告 [localhost-startStop-2] org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory.getObjectInstance Name = happs Property maxActive is not used in DBCP2, use maxTotal instead. maxTotal default value is 8. You have set value of "100" for "maxActive" property, which is being ignored. 09-Sep-2025 17:23:35.780 信息 [localhost-startStop-2] org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory.getObjectInstance Name = happs Ignoring unknown property: value of "10" for "minPoolSize" property 09-Sep-2025 17:23:35.780 信息 [localhost-startStop-2] org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory.getObjectInstanc针对这个问题的报错及解决
最新发布
09-11
"org.apache.kafka.connect.errors.ConnectException: An exception occurred in the change event producer. This connector will be stopped.\n\tat io.debezium.pipeline.ErrorHandler.setProducerThrowable(ErrorHandler.java:42)\n\tat io.debezium.connector.postgresql.PostgresStreamingChangeEventSource.execute(PostgresStreamingChangeEventSource.java:168)\n\tat io.debezium.connector.postgresql.PostgresStreamingChangeEventSource.execute(PostgresStreamingChangeEventSource.java:40)\n\tat io.debezium.pipeline.ChangeEventSourceCoordinator.streamEvents(ChangeEventSourceCoordinator.java:160)\n\tat io.debezium.pipeline.ChangeEventSourceCoordinator.lambda$start$0(ChangeEventSourceCoordinator.java:122)\n\tat java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:266)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n\tat java.lang.Thread.run(Thread.java:748)\nCaused by: io.debezium.DebeziumException: Failed to start replication stream at LSN{6A/B7BA3530}; when setting up multiple connectors for the same database host, please make sure to use a distinct replication slot name for each.\n\tat io.debezium.connector.postgresql.connection.PostgresReplicationConnection.startStreaming(PostgresReplicationConnection.java:312)\n\tat io.debezium.connector.postgresql.connection.PostgresReplicationConnection.startStreaming(PostgresReplicationConnection.java:283)\n\tat io.debezium.connector.postgresql.PostgresStreamingChangeEventSource.execute(PostgresStreamingChangeEventSource.java:130)\n\t... 8 more\nCaused by: org.postgresql.util.PSQLException: ERROR: replication slot \"ganzhouaiot\" is active for PID 212626\n\tat org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532)\n\tat org.postgresql.core.v3.QueryExecutorImpl.processCopyResults(QueryExecutorImpl.java:1200)\n\tat org.postgresql.core.v3.QueryExecutorImpl.startCopy(QueryExecutorImpl.java:882)\n\tat org.postgresql.core.v3.replication.V3ReplicationProtocol.initializeReplication(V3ReplicationProtocol.java:58)\n\tat org.postgresql.core.v3.replication.V3ReplicationProtocol.startLogical(V3ReplicationProtocol.java:42)\n\tat org.postgresql.replication.fluent.ReplicationStreamBuilder$1.start(ReplicationStreamBuilder.java:38)\n\tat org.postgresql.replication.fluent.logical.LogicalStreamBuilder.start(LogicalStreamBuilder.java:37)\n\tat io.debezium.connector.postgresql.connection.PostgresReplicationConnection.startPgReplicationStream(PostgresReplicationConnection.java:582)\n\tat io.debezium.connector.postgresql.connection.PostgresReplicationConnection.createReplicationStream(PostgresReplicationConnection.java:417)\n\tat io.debezium.connector.postgresql.connection.PostgresReplicationConnection.startStreaming(PostgresReplicationConnection.java:304)\n\t... 10 more\n"
05-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值