package concurrentThread;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableAndFuture {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future future = threadPool.submit(
new Callable<String>(){
public String call() throws Exception {
Thread.sleep(2000);
return "Hello";
}
}
);
threadPool.shutdown() ;
System.out.println("等待结果......");
try {
System.out.println("拿到结果: " + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
ExecutorService threadPool1 = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool1);
for(int i=1; i<=10; i++){
final int seq = i;
completionService.submit(
new Callable<Integer>(){
public Integer call() throws Exception {
Thread.sleep(new Random().nextInt(5000));
return seq;
}
}
);
}
for(int i=0; i<10; i++){
System.out.println(completionService.take().get());
}
threadPool1.shutdown() ;
}
}
从网上找了个例子,作者写的有点糙,稍作修改,有个问题不解:为什么call函数中能够直接返回seq, 它怎么能读取到seq这个参数呢? 哪位能给解释下?怀疑这个和内存分配机制有关。
------解决思路----------------------
楼主这个问题和多线程其实没有关系,这是匿名内部类的实现机制决定的。
new Callable<Integer>(){ }这段代码表示定义了一个实现Callable接口的内部类,但因为只用一次,所以这个类没有名字,也就是匿名内部类。Java规定匿名内部类可以直接访问外部类的局部变量和成员变量,而局部变量此时必须用final声明。seq满足这个条件
------解决思路----------------------
内部类在构造的时候就会生成一份外部变量的副本,对线程来说就是new的时候而不是call的时候
------解决思路----------------------
new Callable<Integer>()
属于匿名类
在类初始化的时候,应该是同时将final对象的值拿到的
所以这也是为什么如果要用外部的变量,必须是final