Java 关闭挂钩

2023-12-08

使用 IntelliJ IDE、java 1.8、IDE 中的 lang level 6(以及命令提示符下的默认值)。

从命令行 (Windows 7) 编译并运行:

javac -cp . Main.java
java -cp . Main

给出以下代码,我想要做的是关闭应用程序中所有正在运行的线程(如果操作系统或 JVM 为我做的话,也许我不需要这样做)。我有一个线程 MyThread,它又保存它正在管理的线程列表(当被主线程中断时,将向其列表中的每个线程发送一个中断)。

当我运行代码时,我得到输出Keeping busy.每2秒打印一次。当我按 CTRL-C 时,关闭挂钩运行(我将 println 消息放在那里进行确认),但这就是我看到的所有输出。我从未见过Cancelled.nr main() 的末尾...所以我还必须假设 Cancel 方法也没有运行。

那么,首先我需要关心这个吗?我可以在 isInterrupted 上循环(在 main 中)并让程序停止吗?如何取消所有子线程?

import java.util.HashMap;

class MyThread extends Thread {}

public class Main
{
    private static volatile boolean running = true;
    // List of active threads.
    private HashMap<String, Thread> threads = new HashMap<String, Thread>();

    public static void main(String[] args) throws InterruptedException
    {
        // Get an instance of the Main class.
        Main myApp = new Main();

        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            public void run()
            {
                running = false;
            }
        });

        // Loop until system shutdown.
        while (running && !Thread.currentThread().isInterrupted())
        {
            myApp.CreateMyThread();

            // In real code, I have a wait() here, rather than the following lines.

            System.out.println("Keeping busy.");
            Thread.sleep(2000);
        }

        System.out.println("Cancelled.");

        // Kill all threads.
        myApp.Cancel();

        System.exit(0);
    }

    private void Cancel()
    {
        for (Thread t : threads.values())
        {
            t.interrupt();
        }
    }

    private void CreateMyThread()
    {
        if (threads.get("mythread") instanceof MyThread)
        {
            // Already exists.
            return;
        }

        MyThread t = new MyThread();
        t.start();
        threads.put("mythread", t);
    }
}

EDIT:

所以,我改变了我的代码如下。创建了一个包含哈希图的 Threadlist 类,其中的方法使用关键字“synchronized”来添加/删除线程以及取消所有线程。 main 包含此类的静态实例。然后,我的关闭处理程序调用 CancelThreads 方法来关闭所有正在运行的线程。问题:这真的是线程安全的吗?即:在方法上进行同步实际上会阻止一个方法在另一个方法正在进行时运行吗?

import java.util.HashMap;

class MyThread extends Thread {}

class Threadlist
{
    // List of threads.
    private HashMap<String, Thread> threads = new HashMap<String, Thread>();

    public synchronized void AddThread(String name, Thread thread)
    {
        threads.put(name, thread);
    }

    public synchronized Thread GetThread(String name)
    {
        return threads.get(name);
    }

    public synchronized void CancelThreads()
    {
        for (Thread t : threads.values())
        {
            System.out.printf("Killing a thread by the name of '%s'\n", t.getName());
            t.interrupt();
        }
    }
}

public class Main
{
    private static volatile boolean running = true;
    // List of active threads.
    private static Threadlist threads = new Threadlist();

    public static void main(String[] args) throws InterruptedException
    {
        // Get an instance of the Main class.
        Main myApp = new Main();

        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            public void run()
            {
                threads.CancelThreads();
                running = false;
            }
        });

        // Loop until system shutdown.
        while (running && !Thread.currentThread().isInterrupted())
        {
            myApp.CreateMyThread();

            // In real code, I have a wait() here, rather than the following lines.

            System.out.println("Keeping busy.");
            Thread.sleep(2000);
        }

        System.out.println("Cancelled.");

        System.exit(0);
    }

    private void CreateMyThread()
    {
        if (threads.GetThread("mythread") instanceof MyThread)
        {
            // Already exists.
            return;
        }

        MyThread t = new MyThread();
        t.start();
        threads.AddThread("mythread", t);

}

}

我还开始创建一个 ShutdownHook 类,扩展 Thread,它将通过构造函数接受 main 的线程对象,然后取消 run() 方法中的线程,但我不知道如何更改 main->running 值同时,因此,我的方法上面。


您的关闭挂钩是一个单独的线程,在关闭发生时启动(希望不能保证)。与此同时,你的主线程仍在进行,但即将被杀死。这可能会起作用,但是中断可能不会给你代码中的 2 秒时间,然后它就会杀死主线程。

相反,您应该与关闭挂钩共享生成的线程列表,并让该挂钩尝试直接中断/关闭生成的线程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 关闭挂钩 的相关文章

随机推荐

  • 如何以编程方式在虚拟现实模式下打开街景?

    使用以下代码 我使用特定位置的纬度和经度打开街景视图 Intent streetView new Intent android content Intent ACTION VIEW Uri parse google streetview c
  • C++:如何在 iOS 中已有的 MFC 应用程序中重用加密的 Sqlite 数据库

    我正在进行一个想要重用的项目SQLite的数据库iOS应用程序在我的MFC C 应用 The iOS数据库使用 sqlite3 key 加密 并且使用SQL密码用于数据库处理 And 我在用SQLite 加密借助以下工具进行数据库处理Cpp
  • 如何将 3D 字符数组传递给函数

    我有一个 3D 字符数组 table 我想将其传递给 void 函数 以便它可以对其进行更改 我怎样才能做到这一点 void make char minor char greater 20 30 50 make greater 我想这不会起
  • iOS 自动布局按比例调整 UIView 的大小?

    I m trying to learn Autolayout so I m reading through tutorials and also messing around with some UIViews just to see wh
  • “$”未被识别为内部或外部命令

    我已经广泛搜索了这个问题的答案 但没有找到解决我的特定问题的答案 这就涉及到windows中的命令行了 我正在尝试遵循有关使用 npm 的教程 本教程中的所有命令都以 这个符号开头 即美元符号 当我输入 npm config list 来获
  • 混淆批处理+HTA混合脚本

    以下是混合批处理脚本
  • Safari 推送通知证书问题

    我有一个网站 它使用 Safari 浏览器的推送通知 它工作得很好 直到最近我开始收到一条消息说 推送包签名验证失败 我相信这与最近的 Apple WWDRCA 证书到期有关 现在正在尝试将新证书安装到系统中 他们的文档说 如果您使用 op
  • netezza nzload 与 isnumeric 类似的功能吗?

    我有来自一个平面文件的数据 我正在通过该文件加载到 netezza 中nzload 某些字段类型是数字 但是接收到的数据有时可能包含无效字符 我如何检查以确保数据isnumeric在我的进口中 I saw try cast对于 T Sql
  • 当我从 pandas DataFrame 中采样一行后,如何获取一个单元格的值?

    我有一个pandas我已经成功地从 DataFrame 中采样了一行 但问题之一是它只是返回另一个 DataFrame 我需要读取返回的行并获取该行的特定元素的值 My DataFrame好像 Date Open High Low Clos
  • 如何在Amazon ec2上运行seed.rb文件

    最近 我使用 Amazon EC2 托管了 Ruby on Rails 应用程序弹性豆茎 除了我的 seeds rb 文件之外 一切正常 我的 seeds rb 文件在托管时未执行 我在用活动管理员我还在 seeds rb 文件中定义了第一
  • 有没有办法强制执行模块间依赖/初始化顺序?

    使用Azure IoT Edge 我还没有找到任何方法来保证部署中容器 模块的初始化顺序 举例来说 假设我有 2 个模块 A 和 B A 是服务器 B 是依赖于 A 的客户端 据我所知 无法保证 A 在 B 之前启动 Azure IoT E
  • Raspbian QML 性能不佳

    相同的 QML 程序在 Freescale Yocto 和 Raspberry Raspbian 上运行 这两个测试设备具有几乎相同的 CPUarmv7 但Raspbain这边的表现却非常糟糕 并发出此警告 JIT is disabled
  • 使用 sed 从文件中删除 ^M 字符

    我在文件中有这一行 ULNET PA client sgcib broker keplersecurities KEPLER 我尝试去掉 M 回车 字符 所以我使用了 sed s M g 然而 这确实删除了 M 之后的所有内容 root l
  • spring-boot 2.3.6,如何设置mongo的UUID表示?

    我正在尝试升级到 spring boot 2 3 6 我正在使用 spring data MongoRepositories 没有直接调用 MongoClient 或 MongoClient 获取异常 Caused by org bson
  • Scala 类型推断和多个参数列表

    斯卡拉 2 11 8 考虑以下代码 trait Class A def f1 B gt A arg1 Int ord Ordering B Int def f2 B gt A arg1 Int ord Ordering B Int def
  • add()、replace() 和 addToBackStack() 之间的区别

    调用这些方法的主要区别是什么 fragmentTransaction addToBackStack name fragmentTransaction replace containerViewId fragment tag fragment
  • 如何使用 AnkhSVN 2.x 更改存储库 url

    我正在 VS 2008 上使用 Ankh v2 0 5250 202 连接到我的 Subersion 服务器 VisualSVN 服务器 1 6 3 我的存储库的当前网址是https svnserver 8443 svn foo foo t
  • 错误:“std::cout”中的“operator<<”不匹配

    我意识到此错误通常是由于某些语法或类型问题造成的 但我不确定如何解决此问题 我认为这可能与 findRt 的类型有关 vector
  • 如何用 C++ 从文件中读取单词?

    所以我觉得很无聊 决定制作一款刽子手游戏 我在高中第一次学习 C 时就做过这样的作业 但这是在我接触几何之前 所以不幸的是我在任何方面都没有做得很好 学期结束后我一怒之下把所有东西都扔掉了 我想要制作一个txt文档 然后输入一大堆单词 IE
  • Java 关闭挂钩

    使用 IntelliJ IDE java 1 8 IDE 中的 lang level 6 以及命令提示符下的默认值 从命令行 Windows 7 编译并运行 javac cp Main java java cp Main 给出以下代码 我想