关于线程等待/通知

时间:2014-01-02 11:16:20

标签: java multithreading

我是java中线程概念的初学者。我通过实现等待和通知机制完成了一个小程序,编码如下: -

Example.java

import comp.samplecheck;

public class Example extends Thread {
public static void main(String[] args) {
    samplecheck sample = new samplecheck("First");
    samplecheck sample1 = new samplecheck("Second");
    samplecheck sample2 = new samplecheck("Third");
    samplecheck sample4 = new samplecheck("Fourth");
    samplecheck sample5 = new samplecheck("Fifth");

    sample.initiate(sample);
    sample1.initiate(sample1);
    sample2.initiate(sample2);

    try {
        Thread.sleep(1000);
        sample4.samplefunc(sample4);
    }
    catch(InterruptedException e) {
        System.out.println("Exception "+e);
    }
}
}

samplecheck.java

package comp;

import java.util.List;
import java.util.ArrayList;

public class samplecheck extends Thread {
String get_text;
samplecheck objs;
static List arr = new ArrayList();

public samplecheck(String str) {
    this.get_text = str;
}

public void run() {     
    synchronized(arr) {
        System.out.println(objs.getName()+" Started Processing");

        try {
            arr.wait();
        }
        catch(InterruptedException e) {
            System.out.println("Exception "+e);
        }

        System.out.println("Initial Array Elements Size "+arr.size());
        for(int i=0; i<100 ; i++){
            arr.add(i);
        }

        System.out.println("After Array Elements Size "+arr.size());
        System.out.println("An Object Is Notified");            
    }
}

public void initiate(samplecheck obj) {
    objs = obj;
    objs.start();
}

public void samplefunc(samplecheck obj) {
    objs = obj;

    synchronized(arr) {
        System.out.println("Notification Process");
        System.out.println("After Array Elements Size "+arr.size());
        arr.notify();
    }
}   
}

在samplecheck.java中的samplefunc函数中,如果我给出arr.notify(),我可以得到正确的输出

    Thread-0 Started Processing
    Thread-1 Started Processing
    Thread-2 Started Processing
    Notification Process
    After Array Elements Size 0
    Initial Array Elements Size 0
    After Array Elements Size 100
    An Object Is Notified

但是如果arr.notifyAll()而不是arr.notify()我输出为

    Thread-0 Started Processing
    Thread-2 Started Processing
    Thread-1 Started Processing
    Notification Process
    After Array Elements Size 0
    Initial Array Elements Size 0
    After Array Elements Size 100
    An Object Is Notified
    Initial Array Elements Size 100
    After Array Elements Size 200
    An Object Is Notified
    Initial Array Elements Size 200
    After Array Elements Size 300
    An Object Is Notified

但是根据编码视角,即使我给了notifyAll,只有一个对数组'arr'获得锁定的对象应该被执行并在数组中添加元素和通知消息,即应该显示一个Object Notified。但是这里所有三个对象,即sample,sample1,sample2都会得到通知,并在数组中添加元素。我不知道为什么它以这种方式执行。如果我已经调用了notifyAll方法三次,那么输出应该与上面的格式一样。我希望输出与前一种情况相同(我使用arr.notify()方法获得的输出)。

任何人都可以在这个问题上帮助我....

1 个答案:

答案 0 :(得分:0)

第二个输出是正确的。你对此的理解是错误的。

3个对象正在等待arr,而不仅仅是一个。我认为这解释了调用notifyAll时的输出。

您可能会问这等待的来源?

在每个样本中,sample1,sample2线程都有一个同步块获取arr上的锁定。所以块应该只执行一次,这是你获得锁定时的预期。但是,当您致电wait时,arr上的锁被释放。因此,在sample-1释放锁定之后,sample-2进入synchronized块。

来自wait文档:

  

此方法使当前线程(称为T)将自身置于此对象的等待集中,然后放弃此对象上的所有同步声明。线程T因线程调度而被禁用,并且在发生以下四种情况之一之前处于休眠状态:

     
      
  • 其他一些线程调用此对象的notify方法   线程T碰巧被任意选为线程   惊醒。
  •   
  • 其他一些线程为此调用notifyAll方法   宾语。
  •   
  • 其他一些线程中断了线程T。
  •   
  • 指定的实时时间已经或多或少。但是,如果超时为零,则不考虑实时,并且线程只是等待通知。
  •   
     

然后从该对象的等待集中删除线程T并重新启用线程调度。然后它以通常的方式与其他线程竞争,以便在对象上进行同步;一旦它获得了对象的控制权,它在对象上的所有同步声明都将恢复到原状 - 即,调用wait方法时的情况。线程T然后从wait方法的调用返回。因此,从wait方法返回时,对象和线程T的同步状态与调用wait方法时的状态完全相同。