主线程和从属线程应使用ctrl + c关闭

时间:2012-11-22 15:49:13

标签: java

我正在编写一个程序,其中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);
    }
...

2 个答案:

答案 0 :(得分: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终止线程。

答案 1 :(得分:0)

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

从属线程收集测量值并将它们转发到主线程

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