我是线程话题的新手。我需要异步地向执行程序服务提交任务,还需要获取响应。我试过以下的例子。
案例1:
public class Task implements Callable<Integer> {
Integer i;
public Task(Integer i){
this.i = i;
}
@Override
public Integer call(){
doTask();
}
public Integer doTask(){
syso(i);
return i;
}
}
public class ExecuteTask(){
public void static main (String [] args){
ExecutorService service = Executor.newCachedTheadPool();
for(int i = 0; int <10; i++) {
service.sumbit(new Task(i).doTask());
}
}
}
Output: 0,1,2,3,4,7,9,5,8,6 (expected)
案例2:
public class Task {
Integer i;
public Task(Integer i){
this.i = i;
}
public Integer doTask(){
syso(i);
return i;
}
}
public class ExecuteTask(){
int i;
public void static main (String [] args){
ExecutorService service = Executor.newCachedTheadPool();
for(i = 0; int <10; i++) {
service.sumbit(new Callable<Integer>(){
@Override
public Integer call() {
Integer int = new Task(i).doTask();
return int;
}
});
}
}
}
Output: 1,3,3,6,6,6,10,10,10,10 (not expected)
我的问题是为什么我在上述两种情况下看到不同的结果。如果我没有将i声明为全局变量,那么我将低于错误。
我在封闭范围内定义的局部变量必须是最终的或有效的最终
主要是因为这个我得到了意想不到的输出,因为其他线程可能在奴隶打印时修改了I的值?实时Task类是一个更复杂的对象(它具有从服务获取数据并将其写入DB的逻辑),如果Task类没有实现Callable,我将如何处理这个?
我提交给执行者的实例/任务是否必须实现Callable(为此我需要请求任务类的所有者明确实现Callable)。
或者在运行时创建匿名类并在call()中添加实例化任务类也是正确的方法吗?
答案 0 :(得分:0)
如果我理解你的问题:你可以使用lambdas或方法引用,而那些不必显式实现Callable。只需要遵循相同的约定:返回一些东西(不是void,就像Runnable一样)并且能够抛出异常。 (但这只适用于Java 8+!)