【问题标题】:Thread not stop on calling stop() method线程在调用 stop() 方法时不会停止
【发布时间】:2015-01-21 05:47:40
【问题描述】:

我创建了 java Thread 的示例程序,其中我使用 stop() 方法使用以下程序停止线程

public class App extends Thread
{
    Thread th;

    App(String threadName)
    {
        th = new Thread(threadName);
    }

    public synchronized void run() // Remove synchronized
    {
        for (int i = 0; i < 5; i++) {
            System.out.println(th.getName()+" "+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main( String[] args ) 
    {
       App thread_1 = new App("Thread-1");
       thread_1.start();
       thread_1.setPriority(MAX_PRIORITY); //Comment this
       thread_1.stop();
       App thread_2 = new App("Thread-2");
       thread_2.start();
    }
}

上述程序的输出是:

Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4

即thread_1 没有停止。当我删除同步或代码线程中的优先级立即停止并且输出将是

Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4

我无法理解为什么会这样。

【问题讨论】:

  • Thread#stop 已弃用 - “此方法本质上是不安全的。...”。您应该考虑改用某种locking mechanism
  • @MadProgrammer 我知道亲爱的,但出于知识目的。你能帮我吗
  • 不,stop 方法的功能未定义,这就是问题所在。请改用某种锁定机制。
  • 为什么你认为thread_1没有停止? thread_1.join 将等到 thread_1 退出。由于 thread_2 确实启动了,这意味着 join 解除阻塞,因此 thread_1 真正停止了。
  • @Nikem 如果删除 join(),输出将相同

标签: java multithreading


【解决方案1】:

Thread 类的大多数公共方法都在 Thread 实例本身上同步。 http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/5672a2be515a/src/share/classes/java/lang/Thread.java

您的 run() 方法在 Thread 实例上同步。 stop()方法调用stop(Throwable),同样是在Thread实例上同步的,它的签名是:

@Deprecated
public final synchronized void stop(Throwable obj) {

当线程本身仍在您的synchronized run() 方法中运行时,同步会阻止主线程进入thread_1.stop()


这是一个为什么总是使用私有对象进行同步是明智之举的例子。例如,这样做...

class Foobar {
    private final Object lock = new Object();

    public void do_something() {
        synchronized(lock) {
            ...
        }
    }
}

而不是这样做......

class Foobar {
    public synchronized void do_something() {
        ...
    }
}

第二个版本更冗长(欢迎使用 Java!),但它会阻止您的 Foobar 类的用户将其用作同步对象,而这种方式会干扰它自己将自身用作同步对象。

【讨论】:

  • 避免在 Thread 实例上同步是一个大问题。在这里使用私有锁的替代方法是将 run 方法移动到 Runnable 并在其上进行同步。
  • @NathanHughes,也许我关于私人锁的脚注是模棱两可的。我并不是说 OP 在 App 类中应该有一个私有锁:我真正的意思是,IMO,Thread 类本身应该用(a)私有锁对象来实现,而不是同步,等待并通知客户端可见的实例。
【解决方案2】:

Thread.stop() 已弃用。考虑改用这个:

public class App extends Thread
{
    Thread th;
    volatile boolean bStopThread;
    App(String threadName)
    {
        th = new Thread(threadName);
        bStopThread = false;
    }

    public void stopThread(){
        bStopThread = true;
    }

    public synchronized void run() // Remove synchronized
    {
        for (int i = 0; i < 5; i++) {
            if(bStopThread) return;
            System.out.println(th.getName()+" "+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main( String[] args ) throws InterruptedException
    {
       App thread_1 = new App("Thread-1");
       thread_1.start();
       thread_1.setPriority(MAX_PRIORITY); //Comment this
       thread_1.stopThread();
       App thread_2 = new App("Thread-2");
       thread_2.start();
    }
}

它应该可以按你的意愿工作,虽然我还没有测试过。

【讨论】:

  • 如果你使用 Thread#interrupt 而不是滚动你自己的标志,它会更有响应性;如果线程正忙于睡眠,它将立即从睡眠中返回,请参阅this example
【解决方案3】:

您的应用程序中有 3 个线程:主线程,运行 main 方法的代码,thread_1 和 thread_2。您的主线程在某个时间点 X 启动 thread_1,然后在某个时间点 Y,Y>X 调用 thread_1.stop()。

现在,点 X 和 Y 之间可能发生的情况是 CPU 调度程序可以决定:“我现在让 thread_1 运行”。 Thread_1 将获得 CPU,将运行并打印他的文本。或者,CPU 调度程序可以决定:“主线程现在正在运行......让它运行”。在调用 stop 之前,thread_1 不会获得 CPU 并且不会打印任何内容。

因此,您对 CPU 调度存在无法控制的不确定性。您只能假设提高线程提示调度程序的优先级以选择上述选项中的第一个。

但是。 stop 已被弃用,所以永远不要使用它。并且不要试图猜测多个线程的执行顺序。

【讨论】:

  • 不要认为这是正确的,因为线程 2 正在休眠。我也阅读了javadocs,但使用了stop。由于有趣的正则表达式,jsp 运行超过 10 分钟的示例。有关更多信息,请参阅我的旧问题。 Stop 已弃用,但从未删除。当您无法控制线程时,需要它作为最后的手段
  • 修复有趣的正则表达式。如果您想以任何方式对您的应用程序进行清晰的推理,请不要使用 stop。
  • 好吧,在我们的用例中,它是一个站点的一部分,其中一个屏幕的电子邮件验证,我们使用的正则表达式导致 Java 正则表达式进入一些电子邮件的永无止境的序列(从来没有弄清楚什么)作为一种快速解决方案,我们必须停止线程,否则 CPU 使用率将达到 99% stackoverflow.com/questions/12258589/…
【解决方案4】:

在你的 main 方法中添加一个 try catch。打印堆栈跟踪和捕获的异常消息。在运行方法中相同。然后java会告诉你问题。

MHC 的方法更好,但就像我说的那样 - 有时(很少)当您无法控制线程时,只能调用 stop。但在这种情况下,您确实可以控制它,因此 MHC 方法会很好地工作。

但我看不出您的代码有什么问题 - 它在我的笔记本电脑上运行良好,也许您没有清理并重新编译?更改一些消息,以便您知道最新的代码正在运行

我用过:

package academic.threads;

public class StopThHighPri extends Thread {
    Thread th;
    volatile boolean bStopThread;

    StopThHighPri(String threadName) {
        th = new Thread(threadName);
        bStopThread = false;
    }

    public void stopThread(Thread t) {
        //bStopThread = true;
        try {
            t.stop();
        } catch (Throwable e) {
            System.err.println(" Stop th " + e + " " + e.getMessage());
        }
    }

    public synchronized void run() // Remove synchronized
    {
        try {
            for (int i = 0; i < 5; i++) {
                if (bStopThread)
                    return;
                System.out.println(th.getName() + " " + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("run err " + e);
        }
    }

    public static void main(String[] args) {
        try {
            System.err.println("Code version 002");
            StopThHighPri thread_1 = new StopThHighPri("Thread-1");
            thread_1.start();
            thread_1.setPriority(MAX_PRIORITY); // Comment this
            thread_1.stopThread(thread_1);
            StopThHighPri thread_2 = new StopThHighPri("Thread-2");
            thread_2.start();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("MNain err " + e);
        }
    }
}

输入类似 System.err.println("Code version 002");

并更改 002 、 003。这样您就知道每次编辑课程时最新的代码都在工作。再次学习这是可以的,但不需要在这里使用停止

【讨论】:

  • 在尝试捕获的地方,方法不会抛出任何异常亲爱的。如果你能帮助我会更好
猜你喜欢
  • 2020-08-21
  • 2019-04-28
  • 1970-01-01
  • 2016-05-18
  • 2012-08-27
  • 1970-01-01
  • 2015-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多