The following example code (SSCCE) complains that local variable a must be 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 {}
}
To make things working i change the code to that one
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) {开发者_Python百科 this.x = x; }
public void set(T x) { this.x = x; }
public T get() { return x; }
}
}
My questions:
- Is there something wrong with this ?
- The ObjectRef class exists as standard class in JSE ?
- What is the right way ?
Right way is using FutureTask and 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();
Did you consider using Callable
instead? Callable
can be used when you produce a result, which seem to be your case.
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() );
}
I agree that you should go with Callable and FutureTask.
But it may not be necessary to use an Executor: If you are not going to share that Executor with other code, the three lines required to create it, submit the task, and then shut it down again, seem too verbose. You could just use a Thread.
FutureTask<A> task = new FutureTask(new Callable<A>() {
public A call() {
return list.get(0);
}
});
new Thread(task).start();
A result = task.get();
精彩评论