线程不会在调用 stop() 方法时停止

Thread not stop on calling stop() method

我已经创建了 java 线程的示例程序,我在其中使用 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() 已弃用。考虑改用这个:

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();
    }
}

虽然我没有测试过,但它应该可以如你所愿。

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

现在,X 点和 Y 点之间可能发生的事情是 CPU 调度程序可以决定:"I will now let thread_1 run"。 Thread_1 将得到 CPU,将 运行 并将打印他的文本。或者,CPU 调度程序可以决定:"main thread is now running... let it run"。 thread_1 在调用 stop 之前不会得到 CPU 并且不会打印任何内容。

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

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

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

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

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

我用过:

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。这样您每次编辑 class 时都知道最新的代码正在运行。再次学习这没关系,但不需要使用 stop here

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

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

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

同步阻止主线程进入 thread_1.stop(),而线程本身仍在 运行 中 synchronized run() 方法。


这个例子说明了为什么始终使用私有对象进行同步是明智的。例如,这样做...

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

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

而不是这样做...

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

第二个版本更冗长(欢迎使用 Java!),但它可以防止 Foobar class 的用户以干扰其自身的方式将其用作同步对象将自身用作同步对象。