Search code examples
javamultithreadingjava-threadscompletable-future

Using the faster output from 2 threads


I want to work with two threads in my Java program for a tiny part. I need to give the first call to a database and the second call to an API, both calls with same input, and then work with the output of whichever thread finishes first.

It's my first time programming with threads and I'm very confused. I've seen tutorials and they mainly explain how to get two separate things done with threads so I'm a little lost.

Can someone please help or re-direct me to any useful link they may have?

So far, as I understand it, should it look something like this? :

Thread thread1 = new Thread(func1());
Thread thread2 = new Thread(func2());
thread1.start();
thread2.start();

But then how do I extract the output of the functions? How would I know which one has finished first?

-----------UPDATE 1---------

After trying CompletableFuture (thanks for the help Johan!) I have something like this:

CompletableFuture<Object> getData = CompletableFuture.anyOf(
        CompletableFuture.runAsync(() -> getDataFromDB(clientData)),
        CompletableFuture.runAsync(() -> getDataFromApi(clientData))
    );

    getData.thenApply(dataObject -> {
        // Cast the returned Object to the actual type of your data,
        // assuming both getDataFromDb and getDataFromApi 
        // return the same result type
        Object data = (String) dataObject;

        // Work with the returned data.
        result = (String) data;
    });

But I get this error for getData.thenApply():

The method thenApply(Function) in the type CompletableFuture is not applicable for the arguments (( dataObject) -> {})

Since I know that getData in of type String, would it be okay to just convert it to String and store the result?


Solution

  • As @Johan Hirsch suggests try with CompletableFuture. I've just try this and it works:

        CompletableFuture.anyOf(
                CompletableFuture.supplyAsync(() -> getDataFromDB(clientData)),
                CompletableFuture.supplyAsync(() -> getDataFromApi(clientData)))
                .thenApply(item -> (String) item)
                .thenAccept(result -> {
                    // Consume the data
                    System.out.println(result);
                });
    

    Beware that I'm currently consuming the data so it doesn't return anything. If you just want to pass the result to another CompletableFuture change the thenAccept method for a thenApply