future task cancel
1 FutureTask.cancel 干了啥
//有一个入参,需要说明task是否是可中断的
public boolean cancel(boolean mayInterruptIfRunning) {
if (state != NEW)
return false;
if (mayInterruptIfRunning) {
//尝试修改futuretask的运行状态
if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
return false;
//获取当前线程发出中断信号
Thread t = runner;
if (t != null)
t.interrupt();
//修改task装态为已中断的
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
}
//如果是不可中断的只修改task的状态为cancelled
else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
return false;
//执行finishCompletion方法
/**
* Removes and signals all waiting threads, invokes done(),and nulls out callable.
*/
finishCompletion();
return true;
}
跑完了 返回false
没跑完,输入true,修改为Interrupting,中断t,修改为Interrupted,返回true
没跑完,输入false,修改为Cancelled,返回true
compareAndSwapInt 相等并赋值成功返回true,否则返回false
2 FutureTask.cancel与Thread.interrupt区别
package multithreadci;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* Created by mac on 2023/9/4.
*/
public class TestCancel {
public static void main(String []f ) {
FutureTask subTask = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
Thread.sleep(100000);
return true;
}
});
Thread threadSubTask = new Thread(subTask);
threadSubTask.start();
FutureTask parentTask = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
try {
Object res = subTask.get();
System.out.print(res);
} catch (InterruptedException e) {
e.printStackTrace(); // 2
} catch (ExecutionException e) {
e.printStackTrace(); // 3
} catch (CancellationException e) {
e.printStackTrace(); // 1
// }
//
// try {
// subTask.get();
// } catch (Exception e) {
// e.printStackTrace();
}
return true;
}
});
Thread threadParentTask = new Thread(parentTask);
threadParentTask.start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* 有对.get所在线程inturrupt之后,总是抛Interrupted而不是Cancellation
* 因为get中part唤醒后第一个就是判断是否被中断,根本走不到return和后面的report Cancellatioln
* 如果出现Cancellation,一定没有对.get所在线程interrupt或所在future cancel
*/
int cc = 5;
switch (cc) {
// 仅对subtask的thread interrupt
case 1: // 进3
threadSubTask.interrupt();
break;
// 仅对subtask cancel,不涉及对parent thread的interrupt
case 2: // 进1
subTask.cancel(true);
break;
// 涉及对parent thread的interrupt
case 3: // 进1
subTask.cancel(true);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
parentTask.cancel(true);
break;
case 4: // 进2
subTask.cancel(true);
parentTask.cancel(true);
break;
case 5: // 进2
parentTask.cancel(true);
subTask.cancel(true);
break;
}
}
}).start();
}
}