2

Problem: I have collection of threads start in a loop parallelly. After exiting anyone of thread first ,all other running threads must be terminated. This is what I tried but it doesn't work. Any help is appreciated.

public class ThreadsMain {

    public static void main(String[] args) {
        int SIZE = 3;
        Thread t[] = new Thread[SIZE];

        for (int i = 0; i < SIZE; i++) {
            myThreads th = new myThreads();
            t[i] = new Thread(th);
            t[i].start();

        }

    }
}
Sultan
  • 119
  • 1
  • 12
  • 2
    Possible duplicate of [How to properly stop the Thread in Java?](http://stackoverflow.com/questions/10961714/how-to-properly-stop-the-thread-in-java) – Savior Apr 26 '16 at 18:11
  • What's the problem you're trying to solve? You can't have what you're asking. – Kayaman Apr 26 '16 at 18:16
  • @Pillar can't get the answer from that i am talking about threads running in parallel . – Sultan Apr 26 '16 at 18:16
  • All threads run in parallel. – Savior Apr 26 '16 at 18:16
  • @Kayaman i am talking about terminating of other threads after finding the winning thread ' hope you understand – Sultan Apr 26 '16 at 18:20
  • @Suul I do. Look into the link Pillar posted. – Kayaman Apr 26 '16 at 18:21
  • 1
    @Pillar: the accepted answer for that question is not great. better, see the [api doc for java.util.concurrent.ExecutorCompletionService](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorCompletionService.html), the code sample addresses this exact problem. – Nathan Hughes Apr 26 '16 at 18:35

2 Answers2

3

Here is one way to do it, with a synchronizer implemented with intrinsic locks, and using interruption to cancel the unfinished tasks. The data structure makes a consumer thread block until a producer has submitted a result, then it cancels the other worker threads.

This is a toy example, see the link at the end for the real-world way to do this.

First, here's a threadsafe data structure that accepts results, it allows threads to register as listeners and interrupts them once it has a result submitted to it:

class MyQueue<T> {
    private java.util.List<T> results = new java.util.ArrayList<T>();
    private java.util.List<Thread> listeners = new java.util.ArrayList<Thread>();

    public synchronized void put(T o) {
        results.add(o);
        notifyAll();
        for (Thread listener : listeners) {
            listener.interrupt();
        }
    }

    public synchronized T take() throws InterruptedException {
        while (results.size() == 0) {
            wait();            
        }
        return results.remove(0);
    }

    public synchronized void addListener(Thread t) {
        listeners.add(t);
    }
}

(I don't like having this class know so much about the listeners but I don't want to overthink a toy example either.)

The wait method releases the lock and makes the calling thread go dormant until a notification occurs (or it can just stop waiting arbitrarily). It uses the size property of the results list to know when a result has been submitted. It's not safe to assume that because a thread stopped waiting that you can infer something about the current state, once the thread reacquires the lock it needs to check what the current state actually is. For more about how wait works see this tutorial.

Here's a task that calculates a result (sleeping between iterations just so these threads can run for a while):

class FibTask implements Runnable {

    private final MyQueue<BigInteger> queue;
    private final int n;
    private long sleepTime;

    public FibTask(int n, long sleepTime, MyQueue<BigInteger> queue) {
        this.n = n;
        this.sleepTime = sleepTime;
        this.queue = queue;
    }

    @Override public void run() {
        BigInteger a = BigInteger.valueOf(0);
        BigInteger b = BigInteger.valueOf(1);
        int i = 0;
        try {
            while (!Thread.currentThread().isInterrupted() && i < n) {
                i = i + 1;
                BigInteger temp = a;
                a = b;
                b = a.add(temp);
                Thread.sleep(sleepTime);
            }    
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        if (!Thread.currentThread().isInterrupted()) {
            queue.put(b);
        }
    }
}

Notice in the code above how the Runnable needs to be aware of attempts to interrupt it. Interruption is cooperative, the task is responsible for deciding when to detect interruption and for handling the termination process.

Also if a task involves IO then in some cases interruption doesn't work and you have to close the socket, see this article for more discussion of this.

Here's the main program that runs the threads and gets the result. The MyQueue class is already doing most of the work so this doesn't have to do much:

class Completion {
    public static void main(String ... args) throws Exception {
        MyQueue<BigInteger> queue = new MyQueue<BigInteger>();
        Thread t1 = new Thread(new FibTask(10, 1000L, queue));
        Thread t2 = new Thread(new FibTask(20, 10000L, queue));
        Thread t3 = new Thread(new FibTask(25, 50000L, queue));
        queue.addListener(t1);
        queue.addListener(t2);
        queue.addListener(t3);
        t1.start();
        t2.start();
        t3.start();
        System.out.println(queue.take());
    }
}

Be aware this isn't a fair race because of how the threads' starts are staggered, later threads are at a disadvantage. Submitting tasks to an Executor that initializes a threadpool up front would make sure that the time to start a thread didn't cause a delay here.

For a better way that makes use of java.util.concurrent features like Executors and Futures, see the example given in the API documentation for ExecutorCompletionService.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
-1

A simple approach, use a synchronized class to handle the loop condition:

class ThreadHandler
{
    static Object lock = new Object();
    static boolean finished = false;

    static void finishThreads()
    {
        synchronized(lock)
        {
            finished = true;
        }
    }

    static boolean isFinished()
    {
        boolean result;
        synchronized(lock)
        {
            result = finished;
        }
        return result;
    }
}

And in your runnable

class myThreads implements Runnable
{
    @Override
    public void run()
    {
        while(!ThreadHandler.isFinished())
        {

        }
    }
}
Nadir
  • 1,799
  • 12
  • 20
  • 1
    AtomicBoolean is probably a cleaner way to signal the threads to finish. – AlexC Apr 29 '16 at 17:11
  • @AlexC atomic wont help you here, since it does not synchronize the access, it just sort the instructions applied over the variable – Nadir Apr 29 '16 at 17:12
  • 1
    Isn't that what synchronized is doing in your case? You need a flag to trigger other threads to exit. – AlexC Apr 29 '16 at 21:06
  • @AlexC yes, you are right, I was blind. I would bechmark it though, because volatile variable access is heavy from the performance pov, but yea, it would work and would be more elegant – Nadir Apr 29 '16 at 21:53
  • Accessing a volatile is far faster than a synchronization block when thread count is >1 (think of possible wait times since you are serializing threads based on a class instance. Anyhow, Atomic* are classes based on native implementation using atomic operations that are guaranteed to be thread safe and not need a synchronization block (often performing the operation in 1 cycle). That was the design intention of those classes, interesting code read if you have time. – AlexC May 02 '16 at 12:50
  • @AlexC so, as I thought from the beggining, it was weird that volatile could be used for synchronization. I made a full test, and here are the results: `synchronized(object)` : http://pastebin.com/dhCX18Mb VS `volatile`http://pastebin.com/bYHekd5z . `volatile` is an erroneus solution as it produced an undesired output, so I was right about synchronized – Nadir May 02 '16 at 13:14
  • why are you comparing synchronized to volatile? AtomicBoolean is NOT just volatile, it's an OS native atomic operation; very different. – AlexC May 02 '16 at 20:35
  • @AlexC because you said that volatile access was faster than synchronized. I was benchmarking it. I tried with the output you see (5 theads) and then another 2 tests with 10 and 20. Synchronized was faster (and also giving propper results) – Nadir May 02 '16 at 20:50
  • @AlexC atomicboolean gives the propper result, so about that yeah, is more elegant with the same functionality – Nadir May 02 '16 at 21:27