1

我正在编写一个程序,其中 Main 类初始化并启动一个主线程。这个主线程启动n从线程。该程序应使用终止Ctrl+C。主线程必须停止从线程并最终停止自己。我已经阅读了很多addShutdownHook,这是我的简化实现:

package dictator;

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

public class Main {

    public static void main(String[] args) {
        Master m = new Master();
        m.start();
    }
}

class Master extends Thread {

    List<Slave> slaveMonitor = new ArrayList<Slave>();

    public Master() {
        for (int i = 0; i < 4; i++) {
            Slave slaveThread = new Slave();
            slaveMonitor.add(slaveThread);
        }

        Thread shutDown = new Thread() {
            @Override
            public void run() {
                try {
                    System.out.format("%nShutting down threads...%n");
                    for (Slave s : slaveMonitor) {
                        s.interrupt();
                        s.join();
                    }
                    interrupt()
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        };
        Runtime.getRuntime().addShutdownHook(shutDown);
    }

    @Override
    public void run() {
        for (Slave s : slaveMonitor) {
            s.start();
        }

        while (true) {
            System.out.println(getName() + " - Master");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                System.out.println(getName() + " interrupted.");
               break;
            }
        }
        System.out.println(getName() + " exiting.");
    }
}

class Slave extends Thread {

    public Slave() {}

    @Override 
    public void run() {
        while (true) {
            System.out.println(getName() + " - Slave");
            try {
                Thread.sleep(1500);
            } catch (InterruptedException ex) {
                System.out.println(getName() + " interrupted.");
                break;
            }
        }
    }
}

addShutdownHook捕获信号并终止所有从属线程,但我没有看到主线程退出(行System.out.println(getName() + " interrupted.");和在主线程的System.out.println(getName() + " exiting.");运行主体中。

这是我的终端的输出:

Thread-1 - Slave
Thread-2 - Slave
Thread-3 - Slave
Thread-0 - Master
Thread-4 - Slave
Thread-0 - Master
^C
Shutting down threads...
Thread-1 interrupted.
Thread-2 interrupted.
Thread-3 interrupted.
Thread-4 interrupted.

我不应该看到以下行吗?我做错了什么?

Thread-0 interrupted.
Thread-0 exiting.

更改主线程

class Master extends Thread {

    List<Slave> slaveMonitor = new ArrayList<>();
    List<Thread> killList = new ArrayList<>();

    public Master() {

        for (int i = 0; i < 4; i++) {
            Slave slaveThread = new Slave();
            slaveMonitor.add(slaveThread);
        }
        killList.add(this);

        Thread shutDown = new Thread() {
            @Override
            public void run() {
                try {
                    killList.addAll(slaveMonitor);
                    Collections.reverse(killList);
                    System.out.format("%nShutting down threads...%n");
                    for (Thread t : killList) {
                        t.interrupt();
                        t.join();
                    }
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                    System.out.println("Interrupted shutdown process");
                    System.exit(1);
                }
            }
        };
        Runtime.getRuntime().addShutdownHook(shutDown);
    }
...
4

2 回答 2

1

您的关闭线程永远不会中断主线程。它是与主线程分开的线程,因此当您调用时

   interrupt() 

在其正文中,您要求该线程自行中断。您需要将主线程添加到要终止的线程列表中。

将您的代码更改为:

  List<Thread> killList = new ArrayList<Thread>();
   ....
    for (int i = 0; i < 4; i++) {
        Slave slaveThread = new Slave();
        slaveMonitor.add(slaveThread);
    }
    killList.addAll(slaveMonitor);
    killList.add(this);

并使用killList来终止线程。

于 2012-11-22T16:02:52.443 回答
0

1)创建一个使用两种类型线程的程序:从属(传感器)和主线程。

从属线程收集测量值并将其转发给主线程

为简单起见,从站测量当前时间(System.currentTimeMillis())。只有主线程将值输出到控制台。测量值存储在共享变量中。从机的数量应从控制台读取。

于 2014-11-18T14:56:25.287 回答