2010-02-19 2 views
3

다음 예제 코드 (SSCCE)는 로컬 변수 이 최종해야한다고 불평합니다.내부 익명의 외부 변수에 액세스 Runnable

  1. 이 문제가 있습니다 :
    public class Foo { 
    
        final List<A> list = new ArrayList() {{ add(new A()); }}; 
    
        void foo() { 
         A a; 
         Thread t = new Thread(new Runnable() { 
          public void run() { 
           a = list.get(0); // not good ! 
          } 
         }); 
         t.start(); 
         t.join(0); 
         System.out.println(a); 
        } 
    
        class A {} 
    } 
    

    내가 하나

    public class Foo { 
    
        final List<A> list = new ArrayList() {{ add(new A()); }}; 
    
        void foo() { 
    
         // A a; 
         final ObjectRef x = new ObjectRef(); 
         Thread t = new Thread(new Runnable() { 
    
          public void run() { 
           // a = list.get(0); 
           x.set(list.get(0)); 
          } 
    
         }); 
         t.start(); 
         t.join(0); 
    
         // System.out.println(a); 
         System.out.println(x.get()); 
        } 
    
        class A {} 
    
        class ObjectRef<T> { 
         T x; 
    
         public ObjectRef() {} 
    
         public ObjectRef(T x) { this.x = x; } 
    
         public void set(T x) { this.x = x; } 
    
         public T get() { return x; } 
        } 
    } 
    

    내 질문에 코드를 변경 작업 일을 만들려면?

  2. ObjectRef 클래스는 JSE의 표준 클래스로 존재합니까?
  3. 올바른 방법은 무엇입니까?

답변

3

대신 Callable을 사용해 보셨습니까? 귀하의 사례 인 것처럼 보이는 결과를 산출 할 때 Callable을 사용할 수 있습니다.

final List<A> list = new ArrayList() {{ add(new A()); }}; 

    void foo() { 

     Callable<A> call = new Callable<A> { 
      A call() throws Exception 
      { 
       // do something with the list 
       return list.get(0); 
      } 
     } 

     ExecutorService executor = new ScheduledThreadPoolExecutor(1); 
     Future<A> future = executor.submit(call); 

     System.out.println(future.get()); 
    } 
4

오른쪽 방법은 당신이 호출 가능하고 FutureTask로 가야 동의 FutureTask 및 호출 가능

FutureTask task = new FutureTask(new Callable<A>() { 
    public A call() { 
     return list.get(0); 
    } 
}); 

Executor ex = Executors.newFixedThreadPool(1); 
ex.execute(task); 

// do something else, code is executing in different thread 

A a = task.get(); //get result of execution, will wait if it's not finished yet 


ex.shutdown(); 
+0

'ex.shutdown()'을 잊지 마세요. – Thilo

2

을 사용하고 있습니다.

그러나 Executor를 사용하지 않아도됩니다. Executor를 다른 코드와 공유하지 않으려면 Executor를 만들고, 제출하고, 다시 종료하는 데 필요한 세 줄이 너무 자세하게 보입니다. . 당신은 단지 쓰레드를 사용할 수 있습니다.

FutureTask<A> task = new FutureTask(new Callable<A>() { 
    public A call() { 
     return list.get(0); 
    } 
}); 
new Thread(task).start(); 
A result = task.get();