3

次のコード例 (SSCCE) は、ローカル変数aが final でなければならないことを示しています。

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; }
    }
}

私の質問:

  1. これに何か問題がありますか?
  2. ObjectRef クラスは JSE の標準クラスとして存在しますか?
  3. 正しい方法は何ですか?
4

3 に答える 3

4

正しい方法は FutureTask と Callable を使用することです

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();
于 2010-02-19T10:16:40.097 に答える
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() );
    }
于 2010-02-19T10:13:59.287 に答える
2

Callable と FutureTask を使用する必要があることに同意します。

ただし、Executor を使用する必要がない場合もあります。その Executor を他のコードと共有しない場合、Executor を作成し、タスクを送信し、再度シャットダウンするために必要な 3 行は冗長すぎるように思えます。スレッドを使用できます。

FutureTask<A> task = new FutureTask(new Callable<A>() {
   public A call() {
      return list.get(0);
   }
});
new Thread(task).start();
A result = task.get();
于 2010-02-19T10:49:13.210 に答える