3

我有一个创建 10 个线程的程序,每个线程都有一个无限运行的 while 循环。我需要帮助来有效地实现一个可以有效地停止所有线程的 Shutdown 钩子。由于我想优雅地关闭每个线程,只要它发现停止标志变为 TRUE,它就应该完成。

public class SampleGSH implements Runnable{
    private static boolean stop = false;
    public static void main(String[] args) {
        for(int i = 0; i < 10;i++) {
            Thread t = new Thread(new SampleGSH(), "name"+i);
            t.start();
        }
    }

    @Override
    public void run() {
            Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
                public void run()
                {
                    System.out.println("*******");
                    synchronized (this) 
                    {
                        System.out.println("Turning switch off");
                        stop = true;
                    }
                }
            });

            synchronized (this) {
                while(!stop)
                {
                      //Some logic which should not be killed abruptly once it starts running, a graceful shut down will not allow this code to start
                }
            }   
    }
}

任何帮助将不胜感激。

4

3 回答 3

2

这是一个常见问题解答。如果您有多个线程之间共享的任何字段,则它们需要同步。在这种情况下,您stop应该是volatile. 没有这个,没有任何东西可以确保线程将看到stop更改为true. 有关原子访问的信息,请参阅本教程

请参阅:使用布尔变量停止线程

几个其他评论:

  • 如果要启动多个线程,则应考虑使用ExecutorService
  • 您的while循环位于synchronized块内。这没有任何作用,并且该stop字段不会获得内存同步,因为它在块内部时会从外部更新。
  • 停止线程的另一种方法是interrupt()它。请参阅本教程

    while (!thread.currentThread().isInterrupted()) {
        ...
    }
    ...
    t.interrupt();
    
于 2013-05-05T18:35:32.763 回答
1

您可以为每个线程提供自己的停止布尔值,而不是单个静态停止布尔值。然后在创建它们时存储所有线程对象,并在关闭挂钩线程中将它们的停止布尔值设置为 true(这将在 main 方法中挂钩)。

像这样的东西:

import java.util.ArrayList;
import java.util.List;

public class SampleGSH extends Thread {

    public boolean stop = false;
    private static List<SampleGSH> threads = null;

    public static void main(String[] args) {

        threads = new ArrayList<SampleGSH>();

        int numThreads = 10;
        for (int i = 0; i < numThreads; i++) {
            SampleGSH t = new SampleGSH();
            threads.add(t);
            t.start();
        }

        Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") {
            public void run() {
                System.out.println("*******");
                for (SampleGSH t : threads) {
                    t.stop = true;
                }
            }
        });
    }

    @Override
    public void run() {
        {
            while (!stop) {
                // Some logic which should not be killed abruptly once it starts
                // running, a graceful shut down will not allow this code to
                // start
            }
        }
    }
}
于 2013-05-05T18:41:05.887 回答
1

忘掉那些addShutdownHook废话...保持简单...

  1. 使静态stop变量volatile ...

  2. 然后将此方法添加到 SampleGSH ...

    public void shutdown() { stop = true; }

  3. 然后在你想停止线程时调用它!

于 2013-05-06T09:22:00.933 回答