Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the result of first thread that finishes successfully in java?

Suppose there are multiple threads trying to find a value, whichever thread finds it first should send the output to the main thread and all other threads should be terminated. Example -

public class WorkerThread implements Runnable {
    @Override
    public void run() {
        // some long task here, returns int value
    }
}

public class Main {
    public static void main(String[] args){
         // initialize multiple worker threads here
         // then get result from the thread that completes first
    }
}

I looked into docs and found invokeAny ExecutorService but this will return the result of any thread that has been completed successfully and not necessarily the first one.

like image 536
Vedant Mehra Avatar asked Oct 24 '25 09:10

Vedant Mehra


2 Answers

As @Andy Turner said, use a CompletionService:

    public static class WorkerThread implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            int nextInt = new Random().nextInt(10000);
            try {
                System.out.println("I will cost " + nextInt + " ms to finish job.--" + Thread.currentThread().getName());
                Thread.sleep(nextInt);
            } catch (InterruptedException ite) {
                System.out.println("I am interrupted.--" + Thread.currentThread().getName());
                return -1;
            }
            System.out.println("I am finish.--" + Thread.currentThread().getName());
            return nextInt;
        }
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        int nums = 3;
        ExecutorService executorService = Executors.newFixedThreadPool(nums);
        CompletionService<Integer> completionService = new ExecutorCompletionService<>(executorService);
        while (nums-- > 0) {
            completionService.submit(new WorkerThread());
        }
        Integer firstValue = completionService.take().get();
        System.out.println("FirstValue is " + firstValue);
        executorService.shutdownNow();
    }

And you can see in output, only one thread will complete the job (Because only call completionService#take once ), other threads will be interrupted and exit :

I will cost 8943 ms to finish job.--pool-1-thread-1
I will cost 9020 ms to finish job.--pool-1-thread-2
I will cost 5025 ms to finish job.--pool-1-thread-3
I am finish.--pool-1-thread-3
FirstValue is 5025
I am interrupted.--pool-1-thread-1
I am interrupted.--pool-1-thread-2
like image 127
zysaaa Avatar answered Oct 26 '25 00:10

zysaaa


You can also use CountDownLatch and ExecutorService for achieving this.

Create CountDownLatch object with count = 1.

CountDownLatch latch = new CountDownLatch(1);

Use ExecutorService pool to execute the threads and pass the latch in all the threads.

workerThreadPool.execute(new WorkerThread(latch));

Wait for any thread to complete it's operation.

latch.await();

In the finally block of the thread run, shutdown the latch.

latch.countDown();

As soon as any thread countDown's the latch, the threadpool will stop all the other threads and shutdown.

workerThreadPool.shutdownNow();

The complete example would be below.

import static java.lang.Thread.sleep;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class WorkerThread implements Runnable
{

    CountDownLatch _latch;

    public WorkerThread(CountDownLatch latch)
    {
        _latch = latch;
    }

    @Override
    public void run()
    {
        try
        {
            // some long task here, returns int value
            System.out.println("In thread1 " + this.toString());
            sleep(5000);
        }
        catch (InterruptedException ex)
        {
            System.out.println("thread1 interupted");
        }
        finally
        {

            System.out.println("Finished1 " + this.toString());
            _latch.countDown();
        }
    }
}

class WorkerThread2 implements Runnable
{

    CountDownLatch _latch;

    public WorkerThread2(CountDownLatch latch)
    {
        _latch = latch;
    }

    @Override
    public void run()
    {
        try
        {
            // some long task here, returns int value
            System.out.println("In thread2 " + this.toString());
            sleep(10000);
        }
        catch (InterruptedException ex)
        {
            System.out.println("thread2 interupted");
        }
        finally
        {

            System.out.println("Finished2 " + this.toString());
            _latch.countDown();
        }
    }
}

public class Main
{

    public static void main(String[] args) throws InterruptedException
    {
        ExecutorService workerThreadPool = Executors.newFixedThreadPool(2);

        CountDownLatch latch = new CountDownLatch(1);

        workerThreadPool.execute(new WorkerThread(latch));
        workerThreadPool.execute(new WorkerThread2(latch));

        latch.await();

        workerThreadPool.shutdownNow();
    }
}
like image 45
Udit Jindal Avatar answered Oct 26 '25 00:10

Udit Jindal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!