假设我的应用程序中的组件有类似的界面来运行作业 -
Array
(
[0] => Array
(
[number] => 5613106
)
[1] => Array
(
[number] => 56131064
)
[2] => Array
(
[number] => 56131063
)
)
我想设置我的应用程序,以便异步运行这些作业。期望是调用cancel应该立即执行返回,结果表明它已被取消。
设置此功能的最佳方法是什么?我可以创建一个Thread对象来运行它,它有其他方法可以取消,但我也在查看我不熟悉的Future接口。
FutureTask的问题是取消不优雅,不允许我调用job.cancel()。扩展FutureTask并实现我自己的处理是不是一个好主意?
答案 0 :(得分:1)
当你在任务中调用cancel
时,它会向运行任务的线程发送一个中断信号。您的任务需要定期检查是否已发送该信号,并在有以下情况时作出相应的反应:
if (Thread.interrupted()) {
performNecessaryCleanup();
return;
}
答案 1 :(得分:1)
使用并发时,请使用语言提供的内容,而不是手动实现。
据我了解,ExecutorService应该是适合您的工具,因为您可以:
实施例
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<Future<IResult>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(executor.submit(new Job(i))); //start jobs
}
executor.shutdownNow(); //attempts to stop all running jobs
//program flow immediatly continues
}
就像@JoeC在他的回答中解释的那样,保证所有作业被停止的条件是中断在每个作业中内部管理,因为每个线程都会被标记为<调用shutdownNow()
时,em>中断。
if (Thread.interrupted()) {
//return result cancelled
}
答案 2 :(得分:0)
调用 IJob.execute()或 FutureTask.run()会阻止当前线程,您需要调整 IJob 或 FutureTask 即可。
调度 FutureTask 是最佳选择,消费者可以调用 FutureTask.get()并等待结果(即使您调用 IJob.cancel( )强>)。
我做了一个小小的演示,嘲笑 IJob 和 IResult ,它使用普通线程进行调度,在生产中你应该像以前一样拥有 ExecutorService 发布示例。
如您所见,主线程可以检查调用 FutureTask.isDone()的状态,基本上您正在检查结果是否已设置。设置结果意味着 IJob 的线程已完成。
您可以随时调用 IJob.cancel()来完成 FutureTask 中包装的 IJob ,如果该方法的行为类似于您的评价。
模拟工作:
public class MockJob implements IJob {
private boolean cancelled;
public MockJob() {
}
@Override
public IResult execute() {
int count = 0;
while (!cancelled) {
try {
count++;
System.out.println("Mock Job Thread: count = " + count);
if (count >= 10) {
break;
}
Thread.sleep(1000);
} catch (InterruptedException e) {
cancelled = true;
}
}
return new MockResult(cancelled, count);
}
@Override
public void cancel() {
cancelled = true;
}
}
模拟结果:
public class MockResult implements IResult {
private boolean cancelled;
private int result;
public MockResult(boolean cancelled, int result) {
this.cancelled = cancelled;
this.result = result;
}
public boolean isCancelled() {
return cancelled;
}
public int getResult() {
return result;
}
}
主要类别:
public class Main {
public static void main(String[] args) throws InterruptedException {
// Job
IJob mockJob = new MockJob();
// Async task
FutureTask<IResult> asyncTask = new FutureTask<>(mockJob::execute);
Thread mockJobThread = new Thread(asyncTask);
// Show result
Thread showResultThread = new Thread(() -> {
try {
IResult result = asyncTask.get();
MockResult mockResult = (MockResult) result;
Thread thread = Thread.currentThread();
System.out.println(String.format("%s: isCancelled = %s, result = %d",
thread.getName(),
mockResult.isCancelled(),
mockResult.getResult()
));
} catch (InterruptedException | ExecutionException ex) {
// NO-OP
}
});
// Check status
Thread monitorThread = new Thread(() -> {
try {
while (!asyncTask.isDone()) {
Thread thread = Thread.currentThread();
System.out.println(String.format("%s: asyncTask.isDone = %s",
thread.getName(),
asyncTask.isDone()
));
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
// NO-OP
}
Thread thread = Thread.currentThread();
System.out.println(String.format("%s: asyncTask.isDone = %s",
thread.getName(),
asyncTask.isDone()
));
});
// Async cancel
Thread cancelThread = new Thread(() -> {
try {
// Play with this Thread.sleep, set to 15000
Thread.sleep(5000);
if (!asyncTask.isDone()) {
Thread thread = Thread.currentThread();
System.out.println(String.format("%s: job.cancel()",
thread.getName()
));
mockJob.cancel();
}
} catch (InterruptedException ex) {
// NO-OP
}
});
monitorThread.start();
showResultThread.start();
cancelThread.setDaemon(true);
cancelThread.start();
mockJobThread.start();
}
}
输出(Thread.sleep(5000)):
Thread-2: asyncTask.isDone = false
Thread-0: count = 1
Thread-2: asyncTask.isDone = false
Thread-0: count = 2
Thread-2: asyncTask.isDone = false
Thread-0: count = 3
Thread-2: asyncTask.isDone = false
Thread-0: count = 4
Thread-2: asyncTask.isDone = false
Thread-0: count = 5
Thread-3: job.cancel()
Thread-2: asyncTask.isDone = false
Thread-1: isCancelled = true, result = 5
Thread-2: asyncTask.isDone = true
输出(Thread.sleep(15000)):
Thread-2: asyncTask.isDone = false
Thread-0: count = 1
Thread-2: asyncTask.isDone = false
Thread-0: count = 2
Thread-2: asyncTask.isDone = false
Thread-0: count = 3
Thread-2: asyncTask.isDone = false
Thread-0: count = 4
Thread-2: asyncTask.isDone = false
Thread-0: count = 5
Thread-2: asyncTask.isDone = false
Thread-0: count = 6
Thread-2: asyncTask.isDone = false
Thread-0: count = 7
Thread-2: asyncTask.isDone = false
Thread-0: count = 8
Thread-2: asyncTask.isDone = false
Thread-0: count = 9
Thread-2: asyncTask.isDone = false
Thread-0: count = 10
Thread-1: isCancelled = false, result = 10
Thread-2: asyncTask.isDone = true