使用并发包中的同步器。 FutureTask始终返回null

时间:2012-10-27 20:31:21

标签: java multithreading concurrency executorservice java.util.concurrent

任何人都可以告诉为什么使用FutureTask的以下代码段不起作用? 我的理解是我们可以使用FutureTask,对吧? 为了给出完整的描述:
我在我的代码中偶然发现了一些微妙的错误 简单地说,我创建了一个使用SingleThreadPoolExecutor运行Callable作为参数传递的类 我使用它来运行后台任务并在Eclipse应用程序中显示进度对话框 代码是:

public class TaskRunner <T>  {  

    final static ExecutorService threadPool = Executors.newSingleThreadExecutor();  
    private T taskResult;  

    public T runTask(Callable<T> task, Shell currentShell) throws CustomException{          
        if(currentShell == null){  
            currentShell = new Shell();  
        }  
        final Callable<T> taskToRun = task;       

        ProgressMonitorDialog progressDialog = new ProgressMonitorDialog(currentShell);  
        try {  
            progressDialog.run(false, true, new IRunnableWithProgress() {  

                @SuppressWarnings("unchecked")  
                @Override  
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {  
                    monitor.beginTask("Saving your data!", 100);  

                    FutureTask<T> task = createTask(taskToRun);  
                    Future<?> result = threadPool.submit(task);  
                    while(!result.isDone()){  
                        monitor.worked(1);  
                    }                     
                    try {  
                        taskResult = (T) result.get();  
                        if(taskResult == null){  
                            System.out.println("Result here in return is NULL!");  
                        }  

                    } catch (ExecutionException e1) {  
                        logger.error(e1);  
                    }   
                    catch(Exception e){  
                        logger.error(e);  
                    }               
                }  
            });  
        } catch (InvocationTargetException e) {  
            logger.error(e);  
        } catch (InterruptedException e) {  
            logger.error(e);  
        }       
        return taskResult;  
    }  

    private static <T> FutureTask<T> createTask(Callable<T> theTask){  
        return new FutureTask<T>(theTask);   
    }  
}  

代码任务:

public class MyTask implements Callable<ComplexObject> {    

    private Util helper;  
    private String filePath;  

    public LoadKeystoreTask(Util helper, String filePath) {  
        this.helper = helper;     
        this.filePath = filePath;  
    }  

    @Override  
    public Container call() throws Exception {        
        ComplexObject result = helper.loadData(filePath);  
        if(result == null){  
            System.out.println("ComplexObject IS NULL!");  
        }  
        else{  
            System.out.println("ComplexObject IS NOT NULL!");  
        }   
        return result;  
    }  
}   

问题:
helper.loadData正确返回结果(通过调试和打印语句验证)时,这一行:

taskResult = (T) result.get(); 

始终null 即打印简化:

  

ComplexObject IS NOT NULL!
  这里返回的结果是NULL!

这是通过提交FutureTask来验证的 如果我提交Callable代替:

即。只是改为:

Future<?> result = threadPool.submit(taskToRun);

它有效!为什么用FutureTask包装会导致这个问题?

2 个答案:

答案 0 :(得分:2)

这里不需要

FutureTask

private static <T> FutureTask<T> createTask(Callable<T> theTask){  
    return new FutureTask<T>(theTask);   
}

FutureTask<T> task = createTask(taskToRun);  
Future<?> result = threadPool.submit(task); 

直接submit() Calleble<T>

Future<?> result = threadPool.submit(taskToRun); 

我认为FutureTask不打算在用户代码中使用:

  

此类提供Future

的基本实现

将实施Future留给图书馆。

答案 1 :(得分:0)

这很简单。 FutureTaskRunnable,因此您调用ExecutorService的确切方法为Future<?> submit(Runnable task)。现在让我们来看看javadoc:

  

提交Runnable任务以执行并返回Future   代表那个任务。未来的get方法将会   成功完成后返回 null ...

这是可以理解的。 Runnable仅包含void run()方法。你希望它返回什么结果?

如果您向FutureTask提交Executor,只需使用它即可获得结果:

FutureTask<Integer> task = ...
threadPool.submit(task);
result = task.get();