İhsan Tarık
İhsan Tarık

Reputation: 46

How to execute async methods in Order?

I have a custom asynchronous method and I know threads are executed randomly, but I want to execute them in order.

I want to solve the problem in the main() method.

I've tried Thread.sleep() but it's not useful.

public static void main(String[] args) throws Exception{      
      Monster monster = new Monster();

      System.out.println(1);
      monster.exe();
      System.out.println(2);
      monster.exe();
      System.out.println(3);
      monster.exe();
      System.out.println(4);
}

Class Monster

class Monster {

    public void exe() {

        new Thread(() -> {
            System.out.println("Monster...: "+ Thread.currentThread().getName());
        }).start();
    }
}

Upvotes: 0

Views: 2346

Answers (3)

Alexander Ivanchenko
Alexander Ivanchenko

Reputation: 29038

That's doable, but frankly pointless because such a "parallel" execution even less performant than sequential processing of these tasks.

If you are doing that just as an exercise, that's OK. Otherwise, either don't try to control the execution of these tasks or do it in a single-threaded environment.

For that, you might use method join():

public static void main(String[] args) throws InterruptedException {
    Monster monster = new Monster();
    System.out.println(1);
    Thread thread1 = monster.exe();
    thread1.join();
    System.out.println(2);
    Thread thread2 = monster.exe();
    thread2.join();
    System.out.println(3);
    Thread thread3 = monster.exe();
    thread3.join();
    System.out.println(4);
}

Each call of join() will block the main thread until another thread (on which this method was invoked) isn't finished its job.

Note: method join() throws InterruptedException which is a checked exception and must be either handled with a try/catch or should be signified in the method declaration. I've deliberately chosen the second option in order to make the code simpler and keep focus on what it is intended to do. But you should know that it's not a good practice to add the throws clause to the declaration of the main() method.

A small change was done to the Monster class (method exe() returns a thread that has been created in order to be able to join on it).

public class Monster {
    
    public Thread exe() {
        Thread thread = new Thread(() -> {
            System.out.println("Monster...: "+ Thread.currentThread().getName());
        });
        thread.start();
        return thread;
    }
}

Output

1
Monster...: Thread-0
2
Monster...: Thread-1
3
Monster...: Thread-2
4

Upvotes: 1

Vladimir.V.Bvn
Vladimir.V.Bvn

Reputation: 1118

You can use CompletableFuture and then methods like thenApply().

Please look here: https://www.deadcoderising.com/java8-writing-asynchronous-code-with-completablefuture/

Upvotes: 0

Ken Chan
Ken Chan

Reputation: 90507

Another way to do it is to extract the codes that you want to execute asynchronously into a separate Runnable :

 Runnable newMonstorTask() {
     return ()->System.out.println("Monster...: " + Thread.currentThread().getName());
}

And then use CompletableFuture to configure them to execute in order and asynchronously :

 CompletableFuture.runAsync(newMonstorTask())
        .thenRunAsync(newMonstorTask())
        .thenRunAsync(newMonstorTask())
        .thenRunAsync(newMonstorTask());

Upvotes: 0

Related Questions