-
Enhancement
-
Resolution: Unresolved
-
P4
-
None
-
None
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
The documentation for FutureTask#run(), and for the RunnableFuture#run() interface method that it implements, says that the run() method "Sets this Future to the result of its computation unless it has been cancelled." This implies that the method is synchronous, i.e. that after calling run(), the Future has been set to the result of the computation, implying that the computation has completed, unless it has been cancelled.
In the common case where run() is called only once, the implementation is synchronous.
However, the implementation is not always synchronous.
When FutureTask#run() is called in one thread and then called again in a second thread,
the second call returns immediately without waiting for the computation to complete.
This is inconsistent with the documentation.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the test case code below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Given the current documentation, I would expect the output to be:
Task running...
Calling run() again in main thread.
Task finished
Second run() call returned.
Waiting for result:
Done
However, given the large amount of code that might be affected by changing the implementation, it is probably safer to fix the documentation to match the current behaviour rather than changing the implementation to match the current docs.
ACTUAL -
The actual output is as follows:
Task running...
Calling run() again in main thread.
Second run() call returned.
Waiting for result:
Task finished
Done
Note that "Second run() call returned." is output before "Task finished", indicating that the second run() call was not synchronous.
---------- BEGIN SOURCE ----------
cat > MinimalFutureTaskRun.java <<EOF
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MinimalFutureTaskRun {
public static void main(String[] args) throws Exception {
Callable<String> task = () -> {
System.out.println("Task running...");
Thread.sleep(5000); // Simulate a short task
System.out.println("Task finished");
return "Done";
};
FutureTask<String> futureTask = new FutureTask<>(task);
// First call to run in a new thread
Thread thread1 = new Thread(futureTask);
thread1.start();
Thread.sleep(1000); // Give thread1 a tiny head start
// Second call to run in the main thread
System.out.println("Calling run() again in main thread.");
futureTask.run();
System.out.println("Second run() call returned.");
System.out.println("Waiting for result:");
System.out.println(futureTask.get());
}
}
EOF
javac MinimalFutureTaskRun.java
java MinimalFutureTaskRun
---------- END SOURCE ----------
The documentation for FutureTask#run(), and for the RunnableFuture#run() interface method that it implements, says that the run() method "Sets this Future to the result of its computation unless it has been cancelled." This implies that the method is synchronous, i.e. that after calling run(), the Future has been set to the result of the computation, implying that the computation has completed, unless it has been cancelled.
In the common case where run() is called only once, the implementation is synchronous.
However, the implementation is not always synchronous.
When FutureTask#run() is called in one thread and then called again in a second thread,
the second call returns immediately without waiting for the computation to complete.
This is inconsistent with the documentation.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the test case code below.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Given the current documentation, I would expect the output to be:
Task running...
Calling run() again in main thread.
Task finished
Second run() call returned.
Waiting for result:
Done
However, given the large amount of code that might be affected by changing the implementation, it is probably safer to fix the documentation to match the current behaviour rather than changing the implementation to match the current docs.
ACTUAL -
The actual output is as follows:
Task running...
Calling run() again in main thread.
Second run() call returned.
Waiting for result:
Task finished
Done
Note that "Second run() call returned." is output before "Task finished", indicating that the second run() call was not synchronous.
---------- BEGIN SOURCE ----------
cat > MinimalFutureTaskRun.java <<EOF
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MinimalFutureTaskRun {
public static void main(String[] args) throws Exception {
Callable<String> task = () -> {
System.out.println("Task running...");
Thread.sleep(5000); // Simulate a short task
System.out.println("Task finished");
return "Done";
};
FutureTask<String> futureTask = new FutureTask<>(task);
// First call to run in a new thread
Thread thread1 = new Thread(futureTask);
thread1.start();
Thread.sleep(1000); // Give thread1 a tiny head start
// Second call to run in the main thread
System.out.println("Calling run() again in main thread.");
futureTask.run();
System.out.println("Second run() call returned.");
System.out.println("Waiting for result:");
System.out.println(futureTask.get());
}
}
EOF
javac MinimalFutureTaskRun.java
java MinimalFutureTaskRun
---------- END SOURCE ----------