如何理解这个简单的线程示例?

时间:2014-01-12 18:17:24

标签: java multithreading

它是Java并发中wait()notify()的示例。我对它的理论知识没有解释我这个代码,我无法解释为什么这会给我一个误解的结果。

所以,这是获得想法的代码:

public class ExampleOne {
    public static void main(String[] args) {
        Test b = new Test();
        b.start();
        synchronized(b){
           try{    
              b.wait();
           } catch(InterruptedException ex){
              ex.printStackTrace();
           }
           System.out.println(b.total);
        }
    }
}

class Test extends Thread {
    int total;

    @Override
    public void run(){
        synchronized(this){
            for(int i =0;i<50;i++){
                total+=i;
                System.out.println("I am here");
            }
            notify();
        }
    } 
}

结果是:4950

那么,如何理解这个过程(total如何成为4950)?

我理解如果我调用wait()它会停止调用此方法并唤醒它的对象的线程,然后另一个线程调用notify()。此外,synchronized()块限制线程并且一次只接受一个线程。

  • 因此,当线程调用notify()时,它会在其他情况下变为非活动状态 线程调用wait()?

  • wait()和notify()如何在此代码中扮演角色?还synchronized()阻止?

  • 那么,在这段代码中创建了多少个线程?

我对此感到困惑。帮我解决一下。

2 个答案:

答案 0 :(得分:5)

  

如果我调用wait()它会停止调用此方法的对象的线程并将其唤醒然后另一个线程调用notify()

右。 相同的对象实例上的notify() notifyAll()将唤醒该线程。

  

因此,当线程调用notify()时,它会变为非活动状态,直到其他线程调用wait()?

没有。通知只是发出正在等待同一对象的线程的信号。调用notify()的线程继续运行,并且不会释放它所持有的synchronized锁。

  

wait()和notify()如何在此代码中扮演角色?

没有等待/通知。主线程不会等待计算完成,因此可能会打印0。

  

同步()阻止?

当您使用wait()notify()时,您需要位于synchronized区块中。与您正在等待并通知的synchronized对象实例关联的监视器。此外,synchronized块确保内存同步,因此主线程看到notify字段的更改。每个线程都有一个内存缓存,需要有一些机制来让线程发布它们的更改并查看其他线程对字段所做的更改。

  

那么,在这段代码中创建了多少个线程?

您的代码创建了1个线程,主线程由JVM自动创建。

重要的是要意识到此代码中存在竞争条件。在主线程实际调用wait 之前,新线程可以启动,旋转循环,调用notify并退出。这不太可能,因为启动一个线程需要一些时间,但它可能会发生。在这种情况下,主线程将永远停留在wait,因为没有人可以通知它。

结合其他评论:

  • 我建议您使用this.notify()。重申正在notified
  • 的内容总是好的
  • 正如@JBNizet所指出的,最好使用private final锁定对象而不是Thread对象。
  • 始终建议定义一个implements Runnable而不是扩展线程的类。那你就做new Thread(new TestRunnable()); ...

答案 1 :(得分:2)

为了补充格雷的优秀答案,以下是发生的事情:

主线程:

---------------------------------------------------->
|                   |                            |
start Test thread   waits until notified         wakes up and prints the result

测试线程:

                         ------------------------>
                         |                     |
                         starts running        notifies main thread
                         computes the sum

另请注意,在Thread实例上调用wait()notify()通常被认为是不好的做法。应该使用充当锁的共享对象。 notifyAll()一般应该是首选,甚至更好,应该使用像CountDownLatch这样的更高级别的抽象。