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

时间:2015-01-21 05:47:40

标签: java multithreading

我已经创建了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

我无法理解它为什么会像这样工作。

4 个答案:

答案 0 :(得分:4)

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) {

当线程本身仍在您的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类的用户以干扰其自身作为同步对象的方式将其用作同步对象。

答案 1 :(得分:1)

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

虽然我没有测试过,但它应该可以正常工作。

答案 2 :(得分:0)

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

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

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

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

答案 3 :(得分:0)

在主方法中加入try catch。打印堆栈跟踪和捕获的异常消息。在run方法中相同。然后java会告诉你问题。

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

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

我用过:

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。因此,每次编辑课程时,您都知道最新代码正在运行。再次学习这是可以的,但不需要在这里停止