如何在退出for循环后结束一个线程

时间:2013-11-21 18:36:22

标签: java multithreading synchronized

所以我有一个程序通过使用2个线程打印Hello和Goodbye。 我需要100次打印Hello和Goodbye 100次。 这工作正常,但是,在打印之后,程序挂起并且没有完成。 我有一种感觉,因为线程没有完成。

我想知道最好的办法是什么?

所以我的主要是这样的

public static void main(String [] args)
{
    Object lock = new Object();

    new HelloThread(lock).start();
    new GoodbyeThread(lock).start();
}

这是HelloThread类。 GoodbyeThread看起来一样:

    class HelloThread extends Thread

    {
        private Object lock;
        private boolean isRunning = false;

    HelloThread(Object l)
    {
        this.lock = l;
    }

    public void run()
    {
        for(int i = 0; i < 100; i++)
        {
            synchronized(lock)
            {
                isRunning = true;
                System.out.println("Hello");
                lock.notify();

                try
                {
                    lock.wait();
                }
                catch(InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

我在想可能有一种方法可以使用isRunning变量来关闭线程,但是我不确定最好的方法是什么。 谢谢你的帮助

4 个答案:

答案 0 :(得分:1)

  

这样工作正常,但是在打印之后,程序挂起并且没有完成。我有一种感觉,因为线程没有完成。

如果线程正在离开run()方法,那么它将完成。我怀疑在lock.wait()的第100次打印后,您的帖子卡在"Hello"上。如果您使用jconsole或dump a thread stack trace,您应该能够看到线程卡在哪里。

要认识到的一件事是,如果您调用lock.notify(),则另一个线程将获得通知的唯一时间是lock.wait()。通知呼叫不排队。

答案 1 :(得分:1)

for循环并不重要,关键的事情发生在最后一次迭代中。在另一个线程已经执行其wait()之后,其中一个线程很可能会进入其notify(),从而错过了突破wait()的唯一机会。

答案 2 :(得分:1)

你的GoodbyeThread正在等待你的HelloThread发送一个notify()。

i == 99可能会发生什么:

HelloThread打印“Hello”调用notify(),然后调用wait()

GoodbyeThread打印“Goodbye”调用notify()[此处HelloThread退出for循环并终止],然后调用wait()。

什么都不会调用notify()来结束GoodbyeThread的wait()。

一个修复方法是只调用wait()如果i&lt; 99。

答案 3 :(得分:0)

如上所述:该线程处于死锁状态,因为其中至少有一个仍在等待notify()调用。

想象一下你只有一次跑步(只打印一次“Hello world”):

  1. 线程A启动,打印“Hello”,然后运行notify(),但没有人在监听,然后是wait()。
  2. 线程B启动,打印“World”,然后运行notify()。
  3. 线程A醒来并尝试重新获得监视器lock,但此线程仍由线程B保持,因此线程A必须等待更长时间。
  4. 线程B运行wait(),释放监视器。
  5. 线程A再次醒来,重新获得显示器并完成循环。
  6. 线程B仍在等待,但永远不会被唤醒。

    这可以通过这样的退出通知来解决:

    for(int i = 0; i < 100; i++) {
      // ...
    }
    synchronized (lock) {
      lock.notifyAll();
    }
    

    wait / notify构造是最基本的线程工具,并不适合许多线程问题,因为它们经常会导致死锁或更糟。对于更容易且不易出错的线程概念,您应该使用concurrent package,它有现成的工具可用于解决大多数问题。

    但是必须熟悉这些工具,并且绝对必须围绕这些工具设计代码,反之亦然。现有程序不能只是填充多线程以使其更快,它需要在您编写第一行代码之前为其设计。否则会遇到很多问题,包括结果可能比单线程执行速度慢。