简体   繁体   中英

How can I stop all alive threads from running

So I'm wrapping my head around multithreading and I made a very basic program to play around with. The idea is simply I would start a couple of threads, and each would race down (decrement) to zero at which point one would be declared the winner and the others would stop immediately. I have used a boolean flag, which terminates the other threads but sometimes they carry on for a bit (I guess until they do the check in the while loop to see if run is still true).

I have tried interrupts but my understanding is that these only work on threads that are sleeping, awaiting etc, and the threads I am using a pretty much running the whole time. I have used system.exit(1) but this doesn't stop them either, at least not immediately. Just wondering what more experienced people would do? Basically I just want a thread to say "OK everybody stop what you are doing RIGHT NOW".

Here is the code:

Runnable Class

public class ThreadRunnable implements Runnable {

    private static boolean run;
    private int tick;

    public ThreadRunnable() {
        run = true;
        tick = 5;
    }

    public void run() {
        Thread t = Thread.currentThread();
        while (run) {
            tickDeduction();
            if (tick == 0) {
                System.out.println("Thread " + (Thread.currentThread().getId()) + " WINS");
                this.run = false;
                return;
            }
        }
    }

    public synchronized void tickDeduction() {
        System.out.println("Thread " + (Thread.currentThread().getId()) + " is at tick " + this.tick);
        this.tick--;
    }
}

Main Class

     public static void main(String[] args) {
        ThreadRunnable runnableBlue = new ThreadRunnable();
        ThreadRunnable runnableRed = new ThreadRunnable();
        Thread teamBlue = new Thread(runnableBlue); 
        Thread teamRed = new Thread(runnableRed);
        teamBlue.start();
        teamRed.start();
    }

Basically I just want a thread to say "OK everybody stop what you are doing RIGHT NOW".

There is no way for a Java application to do that to itself. A debugger might be able to do it though. (Certainly, the JDWP protocol has a command to freeze all threads in the target JVM ...)


The closest you could get within a Java application would be to traverse the tree of ThreadGroups and Threads and apply the deprecated Thread.suspend() method to each Thread. (Take care to not pause the current thread ...) But the suspend method is dangerous (see the javadocs), and there is no guarantee that you will see all threads in the traversal. And of course, this (hypothetical) procedure is not instantaneous.

Use a flag that can be claimed only once, and only first time. One such thing is an AtomicBoolean with a compareAndSet() method. To stop other threads you can send an interrupt() .

(Java used to have powers to stop and kill threads, but that leads to issues. Interrupts are the only reliable methods to throw a thread off its normal execution.)

https://ideone.com/1F3bkH

import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;

public class Main {
    public static void main(String[] args) {
        final AtomicBoolean flag = new AtomicBoolean(false);

        final Thread[] runners = new Thread[5];

        final Random random = new Random();

        for (int i = 0 ; i < runners.length; i++){
            runners[i] = new Thread("Runner # " + i){
                @Override
                public void run() {
                    try {
                        // wait for random time
                        Thread.sleep(1000 + random.nextInt(1000));

                        // try to claim the flag
                        boolean claimed = flag.compareAndSet(false,true);

                        if(claimed){
                            System.out.println(this.getName() + " has won the race.");

                            // interrupt others
                            for (Thread t : runners){
                                if(!t.equals(this)){
                                    t.interrupt();
                                }
                            }
                        }else {
                            System.out.println(this.getName() + " has very closely lost the race.");
                        }

                    } catch (InterruptedException e) {
                        System.out.println(this.getName() + " has lost the race.");
                    }
                }
            };
        }

        // get set go
        for (int i = 0 ; i < runners.length; i++){
            runners[i].start();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM