我已经使用执行器提交了一个任务,我需要它在一段时间后停止(例如5分钟).我试过这样做:
- for (Future<?> fut : e.invokeAll(tasks,300,TimeUnit.SECONDS)) {
- try {
- fut.get();
- } catch (CancellationException ex) {
- fut.cancel(true);
- tasks.clear();
- } catch(ExecutionException ex){
- ex.printStackTrace(); //FIXME: gestita con printstack
- }
- }
但是我总是得到一个错误:我有一个共享的Vector需要被任务修改,然后被一个线程读取,即使我停止了所有的任务,如果超时发生我得到:
- Exception in thread "Thread-1" java.util.ConcurrentModificationException
有什么不对? 5分钟后如何停止提交的工作?
解决方法
只是因为你在Future上调用cancel()并不意味着任务会自动停止.你必须在任务中做一些工作,以确保它停止:
>使用cancel(true),以便将中断发送到任务.
>处理InterruptedException.如果您的任务中的函数抛出InterruptedException,请确保在捕获异常时尽快退出.
>如果任务执行连续计算,请定期检查Thread.currentThread().isInterrupted().
例如:
- class LongTask implements Callable<Double> {
- public Double call() {
- // Sleep for a while; handle InterruptedException appropriately
- try {
- Thread.sleep(10000);
- } catch (InterruptedException ex) {
- System.out.println("Exiting gracefully!");
- return null;
- }
- // Compute for a while; check Thread.isInterrupted() periodically
- double sum = 0.0;
- for (long i = 0; i < 10000000; i++) {
- sum += 10.0
- if (Thread.currentThread().isInterrupted()) {
- System.out.println("Exiting gracefully");
- return null;
- }
- }
- return sum;
- }
- }
另外,正如其他帖子所提到的那样,即使使用线程安全的Vector类,ConcurrentModificationException也可以被抛出,因为从Vector获取的迭代器不是线程安全的,因此需要同步.高级for循环使用迭代器,因此请注意:
- final Vector<Double> vector = new Vector<Double>();
- vector.add(1.0);
- vector.add(2.0);
- // Not thread safe! If another thread modifies "vector" during the loop,then
- // a ConcurrentModificationException will be thrown.
- for (Double num : vector) {
- System.out.println(num);
- }
- // You can try this as a quick fix,but it might not be what you want:
- synchronized (vector) { // "vector" must be final
- for (Double num : vector) {
- System.out.println(num);
- }
- }