Java 如果取消时正在运行runnable,如何取消ShceduledFuture并等待runnable停止?
当任何命令在任何ScheduledExecutorService上以固定速率调度时,它返回ScheduledFuture,也可以取消该命令。 但是“取消”不能保证命令在取消返回之后仍然没有执行,例如,因为命令在“Cunely'”被调用时已经在执行的中间。p> 对于大多数用例来说,这就足够了。但当需要在取消后阻塞当前线程时,若命令已经在执行中,我需要处理用例,并等待命令完成。换句话说,若命令仍在执行,那个么调用cancel的线程不应该前进。使用MayInterruptFrunning=true取消也不合适,因为我不想中断当前执行,我只需要等待正常完成 我没有找到如何通过标准JDK类来实现这一需求问题1:我错了吗?这种功能是否存在 所以我决定自己实施: 导入java.util.concurrent.*Java 如果取消时正在运行runnable,如何取消ShceduledFuture并等待runnable停止?,java,java.util.concurrent,Java,Java.util.concurrent,当任何命令在任何ScheduledExecutorService上以固定速率调度时,它返回ScheduledFuture,也可以取消该命令。 但是“取消”不能保证命令在取消返回之后仍然没有执行,例如,因为命令在“Cunely'”被调用时已经在执行的中间。p> 对于大多数用例来说,这就足够了。但当需要在取消后阻塞当前线程时,若命令已经在执行中,我需要处理用例,并等待命令完成。换句话说,若命令仍在执行,那个么调用cancel的线程不应该前进。使用MayInterruptFrunning=true取消
public class GracefullyStoppingScheduledFutureDecorator implements ScheduledFuture {
/**
* @return the scheduled future with method special implementation of "cancel" method,
* which in additional to standard implementation,
* provides strongly guarantee that command is not in the middle of progress when "cancel" returns
*/
public static ScheduledFuture schedule(Runnable command, long initialDelay, long period, TimeUnit unit, ScheduledExecutorService scheduler) {
CancellableCommand cancellableCommand = new CancellableCommand(command);
ScheduledFuture future = scheduler.scheduleAtFixedRate(cancellableCommand, initialDelay, period, unit);
return new GracefullyStoppingScheduledFutureDecorator(future, cancellableCommand);
}
private GracefullyStoppingScheduledFutureDecorator(ScheduledFuture targetFuture, CancellableCommand command) {
this.targetFuture = targetFuture;
this.runnable = command;
}
private final ScheduledFuture targetFuture;
private final CancellableCommand runnable;
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
runnable.cancel();
return targetFuture.cancel(mayInterruptIfRunning);
}
@Override
public long getDelay(TimeUnit unit) {
return targetFuture.getDelay(unit);
}
@Override
public int compareTo(Delayed o) {
return targetFuture.compareTo(o);
}
@Override
public boolean isCancelled() {
return targetFuture.isCancelled();
}
@Override
public boolean isDone() {
return targetFuture.isDone();
}
@Override
public Object get() throws InterruptedException, ExecutionException {
return targetFuture.get();
}
@Override
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return targetFuture.get(timeout, unit);
}
private static class CancellableCommand implements Runnable {
private final Object monitor = new Object();
private final Runnable target;
private boolean cancelled = false;
private CancellableCommand(Runnable target) {
this.target = target;
}
public void cancel() {
synchronized (monitor) {
cancelled = true;
}
}
@Override
public void run() {
synchronized (monitor) {
if (!cancelled) {
target.run();
}
}
}
}
}
问题2:有人能在上面的代码中找到错误吗
问题2:有人能在上面的代码中找到错误吗
假设存在死锁,可通过以下场景再现:
public class GracefullyStoppingScheduledFuture {
/**
* @return the scheduled future with method special implementation of "cancel" method,
* which in additional to standard implementation,
* provides strongly guarantee that command is not in the middle of progress when "cancel" returns
*/
public static GracefullyStoppingScheduledFuture cheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit, ScheduledExecutorService scheduler) {
CancellableCommand cancellableCommand = new CancellableCommand(command);
ScheduledFuture future = scheduler.scheduleAtFixedRate(cancellableCommand, initialDelay, period, unit);
return new GracefullyStoppingScheduledFuture(future, cancellableCommand);
}
private GracefullyStoppingScheduledFuture(ScheduledFuture targetFuture, CancellableCommand command) {
this.targetFuture = targetFuture;
this.runnable = command;
}
private final ScheduledFuture targetFuture;
private final CancellableCommand runnable;
public void cancelAndBeSureOfTermination(boolean mayInterruptIfRunning) throws InterruptedException, ExecutionException {
try {
targetFuture.cancel(mayInterruptIfRunning);
} finally {
runnable.cancel();
}
}
private static class CancellableCommand implements Runnable {
private static final int NOT_EXECUTING = 0;
private static final int IN_PROGRESS = 1;
private static final int CANCELLED_WITHOUT_OBSTRUCTION = 2;
private static final int CANCELLED_IN_MIDDLE_OF_PROGRESS = 3;
private final AtomicInteger state = new AtomicInteger(NOT_EXECUTING);
private final AtomicReference<Thread> executionThread = new AtomicReference<>();
private final CompletableFuture<Void> cancellationFuture = new CompletableFuture<>();
private final Runnable target;
private CancellableCommand(Runnable target) {
this.target = target;
}
public void cancel() throws ExecutionException, InterruptedException {
if (executionThread.get() == Thread.currentThread()) {
// cancel method was called from target by itself
state.set(CANCELLED_IN_MIDDLE_OF_PROGRESS);
return;
}
while (true) {
if (state.get() == CANCELLED_WITHOUT_OBSTRUCTION) {
return;
}
if (state.get() == CANCELLED_IN_MIDDLE_OF_PROGRESS) {
cancellationFuture.get();
return;
}
if (state.compareAndSet(NOT_EXECUTING, CANCELLED_WITHOUT_OBSTRUCTION)) {
return;
}
if (state.compareAndSet(IN_PROGRESS, CANCELLED_IN_MIDDLE_OF_PROGRESS)) {
cancellationFuture.get();
return;
}
}
}
@Override
public void run() {
if (!state.compareAndSet(NOT_EXECUTING, IN_PROGRESS)) {
notifyWaiters();
return;
}
try {
executionThread.set(Thread.currentThread());
target.run();
} finally {
executionThread.set(null);
if (!state.compareAndSet(IN_PROGRESS, NOT_EXECUTING)) {
notifyWaiters();
}
}
}
private void notifyWaiters() {
if (state.get() == CANCELLED_WITHOUT_OBSTRUCTION) {
// no need to notify anything
return;
}
// someone waits for cancelling
cancellationFuture.complete(null);
return;
}
}
公共类GracefullyStoppingsScheduledFuture{
/**
*@使用“取消”方法的特殊实现返回计划的未来方法,
*除了标准实施之外,
*提供强有力的保证,命令在“取消”返回时不在进行中。
*/
公共静态GracefullyStoppingsScheduledFuture ScheduleAtfixedRate(可运行命令、长初始延迟、长周期、时间单位、ScheduledExecutorService调度器){
CancelableCommand CancelableCommand=新的CancelableCommand(命令);
ScheduledFuture future=scheduler.scheduleAtFixedRate(CancelableCommand,initialDelay,period,unit);
返回新的GracefullyStoppingsScheduledFuture(future,CancelableCommand);
}
private GracefullyStoppingsScheduledFuture(ScheduledFuture targetFuture,CancelableCommand){
this.targetFuture=targetFuture;
this.runnable=命令;
}
私人最终计划未来目标未来;
private final cancelablecommand runnable;
public void CancelandBesureof Termination(布尔值MayInterruptFrunning)引发InterruptedException、ExecutionException{
试一试{
targetFuture.cancel(可能中断frunning);
}最后{
runnable.cancel();
}
}
私有静态类CancelableCommand实现Runnable{
私有静态final int NOT_EXECUTING=0;
私有静态final int IN_PROGRESS=1;
私人静态最终int取消,无障碍=2;
进程中间的私有静态最终int取消=3;
私有最终AtomicInteger状态=新的AtomicInteger(未执行);
private final AtomicReference executionThread=新的AtomicReference();
private final CompletableFuture cancellationFuture=新的CompletableFuture();
私人最终可运行目标;
私有可取消命令(可运行目标){
this.target=目标;
}
public void cancel()引发ExecutionException、InterruptedException{
if(executionThread.get()==Thread.currentThread()){
//cancel方法本身已从目标调用
state.set(在进程的中间被取消);
返回;
}
while(true){
if(state.get()==取消,无障碍){
返回;
}
if(state.get()==在进度的中间被取消){
cancellationFuture.get();
返回;
}
if(state.compareAndSet(未执行,取消,无障碍)){
返回;
}
if(state.compareAndSet(进行中,取消进行中){
cancellationFuture.get();
返回;
}
}
}
@凌驾
公开募捐{
if(!state.compareAndSet(未执行,正在进行)){
通知服务员();
返回;
}
试一试{
executionThread.set(Thread.currentThread());
target.run();
}最后{
executionThread.set(null);
如果(!state.compareAndSet(正在进行,而不是正在执行)){
通知服务员();
}
}
}
私人服务员(){
if(state.get()==取消,无障碍){
//不需要通知任何事情
返回;
}
//有人在等取消
cancellationFuture.complete(空);
返回;
}
}