-1

I'm trying to play with async java in my intellij local. My intention is that i will call calucalateAsync() method from main method and then put the debug point on System.out.println("calculate async was called");.

Ideally the submitted task to executors service should be executed concurrently, but the issue is until the execution of the main method is being done, the task is never being executed. Please let me know

Please find below the code:

CompletableFuturePlay.java

public class CompletableFuturePlay {

public void calculateAsync() throws InterruptedException {
    System.out.println("inside calculate async method");
    Executors.newFixedThreadPool(10).submit(() -> {
        System.out.println("inside the submitted task");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("completed the thread");
        return;
    });
    
    System.out.println("outside executores block");
    
}}

PlayGround.java

public class PlayGround {

public static void main(String[] args) throws InterruptedException, ExecutionException {
    CompletableFuturePlay completableFuturePlay = new CompletableFuturePlay();
    completableFuturePlay.calculateAsync();
    System.out.println("calculate async was called");
}}

Output I'm seeing in terminal: enter image description here

16
  • "... but the issue is until the execution of the main method is being done, the task is never being executed." - How did you come to this conclusion? Commented Dec 27, 2023 at 13:42
  • @Turing85 until i play the breakpoint on sout in main method, the submitted code was not being executed. I waited for more than 10 mins and tried multiple times Commented Dec 27, 2023 at 13:43
  • unable to reproduce - with posted code, I get 4 lines of output, last one being "completed the thread" when stopping at the line of "calculate async was called" (but I am using Eclipse) What exactly is the output you are seeing? Commented Dec 27, 2023 at 13:46
  • 2
    A debugger may limit parallel execution to aid debugging. We see this regularly in web applications. If we hit an endpoint to trigger a breakpoint and then (while the debugger stays at the breakpoint) hit the endpoint or even any other endpoint, the browser keeps loading. Commented Dec 27, 2023 at 13:47
  • 2
    but i was thinking if i put debug point in main method, ideally even without explicit Thread.sleep() in main method, the task should get executed in parallel thread: it depends. When you set the breakpoint, you have the option to stop only the current thread, or all threads (I don't know the parallelism in Eclipse, but in IntelliJ is by default "all threads" and you can choose to stop only the current thread). If you're blocking all threads, you may see the async task start (it depends on who gets there first), but you'll never see it ending because of Thread.sleep. Commented Dec 27, 2023 at 14:04

1 Answer 1

1

Breakpoints can suspend:

  • All threads
  • Just the current thread

By default, in IntelliJ Idea, a breakpoint will suspend all threads.

If you launch main (that will run calculateAsync on a separate thread) and you set a breakpoint on the line coming just after the call to calculateAsync that suspends all threads, what will happen is:

  1. Randomly, the beginning of calculateAsync may appear before you hit the breakpoint. However, this is not very likely (the thread has to fork, which takes "some time", so it's more likely that you hit the main breakpoint before the thread actually has the time to start.
  2. The main breakpoint is hit, so all threads will stop (here including the async thread that is running calculateAsync)
  3. Hence, because of the Thread.sleep within the second thread, you will never see the end of it until when the breakpoint is not released.

The "easiest" option to observe the wished behavior is to set the breakpoint to suspend current thread only. If you do that, the secondary thread will be free to run even after you hit your breakpoint and so you will see what you wish to see.

However, this is not a solid way to setup a multi-threading test. My suggestion is to use a CountDownLatch as follows (p.s. I'm writing the code directly on StackOverflow so I may be doing some mistake, please use some tolerance when actually running it):

public class CompletableFuturePlay {

public void calculateAsync(CountDownLatch latch, ExecutorService executor) throws InterruptedException {
    System.out.println("Scheduling asynchronous execution");
    executor.submit(() -> {
        System.out.println("Asynchrounous execution started");
        // do whatever consuming job here. You can mock it with a Thread.sleep if you want
        System.out.println("Asynchronous execution ended");
        latch.countDown(); //send a signal to the latch that your job is over
        return;
    });
    
    System.out.println("Scheduled asynchronous execution");
    
}}

... and then the usage:

public class PlayGround {

public static void main(String[] args) throws InterruptedException, ExecutionException {
    ExecutorService executor = Executors.newFixedThreadPool(10);
    CountDownLatch latch = new CountDownLatch(1); //<-- only 1 is enough
    CompletableFuturePlay completableFuturePlay = new CompletableFuturePlay();
    completableFuturePlay.calculateAsync(latch, executor);
    System.out.println("calculate async was called");
    latch.await(1, Time.MINUTES); //<-- ask the main thread to wait for the other thread to complete the execution - timeout after 1 minute
    System.out.println("resume execution of main thread");
}}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.