very basic code to run asynchronous method.
when I run the following code the runAsync doesn't run.
what I'm missing?
the result run only the sync code .
public class Main {
public static void main(String[] args) {
runAsync("run async command ans wait 10000");
System.out.println("sync commands ");
}
public static void runAsync(String inputStr) {
CompletableFuture.runAsync(() -> {
List<String> strings = Arrays.asList(inputStr.split(" "));
int sleep = Integer.parseInt(strings.get(strings.size() - 1));
try {
sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("async command ");
});
}
}
I expect to get first the "sync commands" then the "async command "
but get only the sync message
Your task will run in some other Thread(by default in a Thread from ForkJoinPool) and you are not waiting for it to finish - the main Thread ends before your async task is executed/submitted. You can call CompletableFuture::join to wait for it to finish and it will block the main Thread until it finishes :
CompletableFuture.runAsync(() -> {
List<String> strings = Arrays.asList(inputStr.split(" "));
int sleep = Integer.parseInt(strings.get(strings.size() - 1));
try {
sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("async command ");
}).join(); //here call the join
or like :
CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
//...
});
cf.join();
You need to wait for the async task to be completed by using join, for example:
public static void main(String[] args) {
CompletableFuture<Void> future = runAsync("run async command ans wait 10000");
future.join();
System.out.println("sync commands ");
}
public static CompletableFuture<Void> runAsync(String inputStr) {
return CompletableFuture.runAsync(() -> {
List<String> strings = Arrays.asList(inputStr.split(" "));
int sleep = Integer.parseInt(strings.get(strings.size() - 1));
try {
sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("async command ");
});
}
It does run, but it runs on another thread and you're not waiting or doing anything with the result. As Javadoc of CompletableFuture.runAsync() says:
Returns a new CompletableFuture that is asynchronously completed by a
task running in the ForkJoinPool.commonPool() after it runs the given
action.
runAsync() is useful for tasks that don't return anything. If you want a result from it you should use supplyAsync() which returns a CompletableFuture<T>
Then you can get the result from it:
// Run a task specified by a Supplier object asynchronously
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
#Override
public String get() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return "Result of the asynchronous computation";
}
});
// Block and get the result of the Future
String result = future.get();
System.out.println(result);
Related
This question already has answers here:
FutureTask get vs run, task never finishes
(3 answers)
Closed 9 months ago.
I try to make an API aysnchronous as:
Future<Integer> fASync(int x) {
return new FutureTask(() -> {
try {
Thread.sleep(new Random().nextInt(1, 3) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return x * x;
});
}
..then I try to use it:
Future<Integer> asyncCall = fASync(x);
asyncCall .get();
But this never completes and call just blocks.
Is this not correct way of making your API asynchronous?
You have declared a FutureTask but haven't actually run it so a call to asyncCall.get() will block forever.
Here is your example with extra logging and adding a step to execute the task in a new ExecutorService.
static FutureTask<Integer> fASync(int x) {
System.out.println("fASync("+x+") called");
return new FutureTask<>(() -> {
System.out.println("fASync("+x+") FutureTask has started");
try {
Thread.sleep(new Random().nextInt(1, 3) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("fASync("+x+") FutureTask has ended");
return x * x;
});
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService exec = Executors.newFixedThreadPool(1);
FutureTask<Integer> task = fASync(5);
// MUST execute the task or task.get() will block forever
exec.execute(task);
System.out.println("task.get()="+task.get());
exec.shutdown();
exec.awaitTermination(1, TimeUnit.DAYS);
System.out.println("ENDED");
}
If you enable the exec.execute(task); line it will print these messages and complete task.get(), instead of printing the first line only and no response from task.get():
fASync(5) called
fASync(5) FutureTask has started
fASync(5) FutureTask has ended
task.get()=25
ENDED
I'm trying to run an async bash command from a java file and wait for it to finish before I continue the java code execution.
At this moment I've tried using Callable like so:
class AsyncBashCmds implements Callable{
#Override
public String call() throws Exception {
try {
String[] cmd = { "grep", "-ir", "<" , "."};
Runtime.getRuntime().exec(cmd);
return "true"; // need to hold this before the execution is completed.
} catch (Exception e) {
return "false";
}
}
}
and I call it like so:
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> future = executorService.submit(new runCPPinShell(hookResponse));
String isFinishedRunningScript = future.get();
Thanks!!!
An easier way is to use Java 9+ .onExit():
private static CompletableFuture<String> runCmd(String... args) {
try {
return Runtime.getRuntime().exec(args)
.onExit().thenApply(pr -> "true");
} catch (IOException e) {
return CompletableFuture.completedFuture("false");
}
}
Future<String> future = runCmd("grep", "-ir", "<" , ".");
String isFinishedRunningScript = future.get(); // Note - THIS will block.
If you want to block anyway, use .waitFor().
Facing the problem with the ThreadPoolExecutor in Java.
How can I execute a continuous task using it? For example, I want to execute something like this:
#Async
void MyVoid(){
Globals.getInstance().increment();
System.out.println(Thread.currentThread().getName()+" iteration # "+ Globals.getInstance().Iterator);
}
I want it to run forever in 2 parallel asynchronous threads until the user sends a request to stop the ThreadPoolExecutor in the "/stop" controller.
If I use this for example:
#Controller
#RequestMapping("api/test")
public class SendController {
ThreadPoolExecutor executor = new ErrorReportingThreadPoolExecutor(5);
boolean IsRunning = true;
#RequestMapping(value = "/start_new", method = RequestMethod.POST)
public Callable<String> StartNewTask(#RequestBody LaunchSend sendobj) throws IOException, InterruptedException {
Runnable runnable = () -> { MyVoid();};
executor.setCorePoolSize(2);
executor.setMaximumPoolSize(2);
while (IsRunning) {
executor.execute(runnable);
System.out.println("Active threads: " + executor.getActiveCount());
}
return () -> "Callable result";
}
#RequestMapping(value = "/stop", method = RequestMethod.GET)
public Callable<String> StopTasks() {
executor.shutdown(); //for test
if(SecurityContextHolder.getContext().getAuthentication().getName() != null && SecurityContextHolder.getContext().getAuthentication().getName() != "anonymousUser") {
executor.shutdown();
return () -> "Callable result good";
}
else { return () -> "Callable result bad";}
}
}
public class ErrorReportingThreadPoolExecutor extends ThreadPoolExecutor {
public ErrorReportingThreadPoolExecutor(int nThreads) {
super(nThreads, nThreads,
0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
#Override
protected void afterExecute(Runnable task, Throwable thrown) {
super.afterExecute(task, thrown);
if (thrown != null) {
// an unexpected exception happened inside ThreadPoolExecutor
thrown.printStackTrace();
}
if (task instanceof Future<?>) {
// try getting result
// if an exception happened in the job, it'll be thrown here
try {
Object result = ((Future<?>)task).get();
} catch (CancellationException e) {
// the job get canceled (may happen at any state)
e.printStackTrace();
} catch (ExecutionException e) {
// some uncaught exception happened during execution
e.printStackTrace();
} catch (InterruptedException e) {
// current thread is interrupted
// ignore, just re-throw
Thread.currentThread().interrupt();
}
}
}
}
I'm getting the following errors:
As I understood, a lot of tasks got submitted into the 'executor' queue within a few seconds and then the executor handled all them. (But I need each thread to wait before the current task ends and then submit the new one to the executor, I think.)
HTTP Requests to these controllers are forever "IDLE" until the next request comes, i.e. after sending a request to /api/test/start_new the controller's code executed tasks that are running, but the request is IDLE.
How can I do this in Java?
P.S. Spring MVC is used in the project. It has its own implementation of ThreadPoolExecutor - ThreadPoolTaskExecutor, but I am facing similar problems with it.
I am trying to signal between two threads using the below FutureResult class which extends FutureTask class. When run the script, it prints the following result.
SENDING: 0
SENT: 0
POLL: FutureResult#513431
SIGNALLED: FutureResult#513431
Then the program hang up forever. I expect FutureResult instance should return the value from it's blocking get method. Then print the result in the console. But FutureResult.get is blocking forever.
import java.util.concurrent.*;
/**
* Created by someone on 20/08/2015.
*/
final public class FutureResult<T> extends FutureTask<T> {
private static final Object SS = "SS";
public FutureResult() {
super(() -> null);
}
public void signal(final T value) {
set(value);
}
public void signalError(final Throwable throwable) {
setException(throwable);
}
public static void main(String... args) throws Exception {
final ArrayBlockingQueue<FutureResult> queue = new ArrayBlockingQueue<>(1000000);
new Thread(() -> {
while (true) {
try {
final FutureResult poll = queue.take();
System.out.println("POLL: " + poll);
if (poll != null) {
poll.signal(SS);
System.out.println("SIGNALLED: " + poll);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 1; i++) {
final FutureResult<Object> result = new FutureResult<>();
System.out.println("SENDING: " + i);
queue.offer(new FutureResult());
try {
System.out.println("SENT: " + i);
result.get();
System.out.println("GOT : " + i);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}).start();
}
}
This is the problem:
queue.offer(new FutureResult());
You're setting the value on one FutureResult, but that's not the one you're waiting for. Just change that line to:
queue.offer(result);
and it works fine.
Looks like the confusion is in the use of FutureTask. FutureTask is designed as a Runnable; running it is necessary.
Honestly, based on the code, it looks like the custom code is implementing something similar to FutureTask. If the intent here is to learn to use FutureTask, then create a FutureTask instance with a "run" method, and then execute that run method. On completion of the run method, the FutureTask.get() will complete.
I hava a test, with:
#test(timeout = 50000)
I want to do some operations if the test fails because the timeout, and only then.
I try the next:
#Test(timeout=60000)
public void test1() {
try{
// code
}
catch(Exception e){
//operations after time out
}
}
But it doesn't work. Any help?
It's not possible to do what you described here with JUnit's timeout parameter because it doesn't provide a callback to handle the operations after it has timed out.
But, you can certainly write your own test harness to do just that. In the below example, I want the code to execute within one second but my actual code execution takes 2 seconds. In this case, we catch the TimeoutException and you can perform your additional operation within that catch block.
#Test
public void testMe() {
// test must finish within one second
int expectedExecutionInSeconds = 1;
RunnableFuture<String> runnableFuture = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
// your actual code goes in here
Thread.sleep(2000);
return "ok";
}
});
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(runnableFuture);
try {
String result = runnableFuture.get(expectedExecutionInSeconds, TimeUnit.SECONDS);
assertEquals("ok", result);
}
catch (TimeoutException ex) {
// stop code
runnableFuture.cancel(true);
System.out.println("do other stuff");
}
catch (Exception e) {
fail("other stuff is failing");
}
executorService.shutdown();
}