当前位置: 代码迷 >> J2SE >> 关于Java并发多线程的一个代码有关问题
  详细解决方案

关于Java并发多线程的一个代码有关问题

热度:93   发布时间:2016-04-23 19:42:46.0
关于Java并发多线程的一个代码问题
本帖最后由 cloudeagle_bupt 于 2015-09-14 11:42:22 编辑

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
  相关解决方案