【问题标题】:Kill a java thread by thread name通过线程名称杀死一个java线程
【发布时间】:2019-12-12 17:33:27
【问题描述】:

我有一个每 15 秒运行一次的脚本,它每次都会创建一个新线程。有时这个线程会卡住并阻止我的程序的同步过程。现在,如果线程卡住了 20 个循环,我想终止具有特定名称的进程。这是我的代码:

public void actionPerformed(ActionEvent e) {


        Date dNow = new Date( );
        SimpleDateFormat ft = new SimpleDateFormat ("dd-MM-yyyy HH:mm:ss");
        System.out.println(ft.format(dNow));

        ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
        int noThreads = currentGroup.activeCount();
        Thread[] lstThreads = new Thread[noThreads];
        currentGroup.enumerate(lstThreads);
        boolean loopthreadfound = false;
        for (int i = 0; i < noThreads; i++){
        try{    
        if (lstThreads[i].getName() == "loopthread"){loopthreadfound = true;}           
        }catch(Exception e1){System.out.println(e1);}
        }

        if (loopthreadfound == false){
            loopthreadcounter = 0;
            //Starten in nieuwe thread
            Thread loopthread = new Thread() {

            public void run() {

                try {
                    checkonoffline();
                    checkDBupdates();
                    } catch (JSONException | SQLException | IOException e1) {
                    System.out.println(e1);
                    }
            }

            };

            loopthread.setName("loopthread");
            loopthread.start();

        }else{

            loopthreadcounter++;
            System.out.println("Loopthread already running...   counter: " + loopthreadcounter);        

            if (loopthreadcounter > 20){

             // HERE I WANT TO KILL THE THREAD "loopthread "

            }
        }

}

【问题讨论】:

  • 为什么要按名字杀掉它?为什么不保留对线程的引用,并通过引用(以某种方式)杀死它?
  • 也很好...我只是想以某种方式杀死它。建议如何采纳代码?
  • 另外,你是如何杀死线程的?如果您使用的是Thread#stop(),那是不安全且已弃用的。相反,我会向线程发送一个中断信号,并让它们定期检查它。
  • "这个线程偶尔会卡住" 为什么不直接解决这个潜在问题...?
  • 可以完全中断checkDBupdates 操作吗?您可以尝试拨打loopthread.interrupt()。线程会死吗?

标签: java multithreading


【解决方案1】:

通常,线程名称不是唯一的。如果您将StringThread 相关联,并且该字符串标识了您要停止的线程,请自行跟踪它,而不是将其视为线程名称。

即创建一个Map&lt;String, Thread&gt;。稍后,您可以通过“名称”从映射中获取正确的线程并终止它。

请注意,stop() 已弃用。您应该找到正确的方法来终止、中断或以其他方式终止被阻止的操作。

【讨论】:

    【解决方案2】:

    你不能在 java 中杀死线程。

    所以让我们退后一步:你有问题,你想:我知道!我会杀死线程...我该怎么做?

    错误的策略。 “从外部”(例如,而不是从线程本身的代码内部)使线程结束的最常见方法是告诉线程自行清理。不管它会不会,那就是……你写一些代码让它发生。

    对于您的情况:大概是某些 I/O 操作被卡住了。对于大多数 I/O 和大多数操作系统,您可以中断线程;这会导致 IOException 发生,从而“解除”任何被卡住的东西。我给你举个例子。我将使用 Thread.sleep 而不是 I/O 操作,因为 Java 规范保证了可中断性:

    在线程代码中:

    public void run() {
        while (!Thread.interrupted()) {
            doExpensiveOp();
            try {
                // sleep a long time
                Thread.sleep(1000000);
            } catch (InterruptedException e) {
                return;
            }
        }
    }
    

    在控制代码中:

    Thread x = ... that thread.;
    x.interrupt();
    

    中断方法将“提高中断标志”,仅此而已。但是,许多 java 核心库调用与它交互。例如,定义为“throw InterruptedException”的 ALL 方法如果在线程中断时处于睡眠状态,则将立即退出,并且如果标志为 up 并且您调用这些方法之一,它们不会根本不运行,他们立即退出该异常。我们还在 while 循环中检查标志的状态。所以,如果我们在 sleep() 操作中,如果你打断它,上面的线程代码肯定会退出。如果线程当前处于其昂贵的操作部分,则将发生以下三种情况之一:

    1. 这个操作完全忽略了它。这当然是可能的;只有声明抛出 InterruptedEx 的方法才能保证正确处理它。至少,在操作结束的那一刻,你的线程肯定会退出,因为对 sleep 的调用会立即抛出 InterruptedEx。

    2. 这个操作会处理它。例如,通过抛出带有“中断”文本的 IOException。

    3. 操作员做了一些奇怪的事情。正如上面的 sn-p 所示,它只是代码。您可以捕获 InterruptedException 并且什么都不做,从而清除标志而不是实际结束。 interrupt() 方法不会强制关闭或停止任何东西,Thread 上也没有任何方法可以用来强制停止它。没有内置代码(java.* 包中的东西)做这样的事情;他们总是要么忽略它,要么抛出InterruptedException,要么抛出相关异常;几乎总是IOException

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-29
      • 2014-06-07
      • 2012-05-25
      相关资源
      最近更新 更多