调用notifyAll()时如何获得相同的监视器?

时间:2015-04-10 07:12:13

标签: java multithreading

主线程创建这两个线程的两个线程t1和t2 run()方法创建两个新线程c1和c2.I想要一个场景,直到c1& c2(t1)处于活动状态t2才会开始执行。 在我的代码中,notify和wait导致Runtime Exception。因为它们不在synchronized块中,怎么做?

public class childTcreat2newthread {

    public static void main(String[] args) throws InterruptedException {
        Thread mainT=Thread.currentThread();
        Target ra=new Target("a");
        Thread t1=new Thread(ra);
        t1.start();
        t1.join();

        while(ra.getC1().isAlive()==true||ra.getC2().isAlive()==true){
        synchronized (mainT) {
        mainT.wait();
        }}
        new Thread(new Target("b")).start();}}



class Target implements Runnable{
    Thread c1=new Thread(new Target1("1"));

    Thread c2=new Thread(new Target1("2"));
    String msg;
    Target(String msg){
        this.msg=msg;
    }
    @Override
    public void run() {


        for(int j=0;j<100000;j++){
            for(int i=0;i<10000;i++){
                if(i%10000==0&&j%10000==0){System.out.print(msg);}
            }}

        t1.start();

        t2.start();
    }

    public Thread getC1(){return c1;}
    public Thread getC2(){return c2;}
}

class Target1 implements Runnable   {

    String msg;
    Target1(String msg){
        this.msg=msg;
    }

    @Override
    public synchronized void run() {
        for(int j=0;j<100000;j++){
            for(int i=0;i<100000;i++){
                if(i%100000==0&&j%10000==0){System.out.print(msg);}
            }
        }
        try{

        notifyAll();
        System.out.println("K");}catch(IllegalMonitorStateException e){System.out.println("\nIllegalMonitorStateException!! in "+msg+"\n");}
    }
}

wait()告诉调用线程放弃监视器并进入休眠状态,直到其他线程进入同一监视器并调用notify()。调用notify时无法获得相同的监视器。如何这样做?

至于我对线程t1&amp;的理解t2这里没有共同的对象访问哪个对象我们应该通过同步锁来调用wait()和notify()?

2 个答案:

答案 0 :(得分:0)

notify,notifyAll,等待调用应该在同一个对象的监视器中完成。应该有一个像Object这样的共享对象,你应该围绕它构建你的逻辑。例如:

public class ClassA{

    Object lockObject=new Object(); 

    //Thread A will call this method
    public void  methodA(){
         synchronized(lockObject){
             while(!aCondition)
                 lockObject.wait();
         }
    }
    //Thread B will call this method
    public void  methodB(){
         synchronized(lockObject){
             aCondition=true;
             lockObject.notify();
         }
    }

}

答案 1 :(得分:0)

as @JB Nizet指出你应该使用join等待fot thread终止

修改 因为你不能使用加入我建议你使用CountDownLatch 其文件说明:

  

允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。

这就是你要求的。

第二次编辑

以下是使用 HomeMade 使用wait和notify的CountDownLatch等待线程终止的代码的修改版本。

    import java.util.concurrent.CountDownLatch;

public class childTcreat2newthread {

    public static void main(String[] args) throws InterruptedException {
        MyCountDownLatch doneSignal = new MyCountDownLatch(2);

        Target ra = new Target("a",doneSignal);
        Thread t1 = new Thread(ra);
        t1.start();
        doneSignal.await();
        System.out.println("after await ");
        MyCountDownLatch doneSignal1 = new MyCountDownLatch(2);
        new Thread(new Target("b",doneSignal1)).start();
    }
}

class Target implements Runnable {
    private Thread c1;
    private Thread c2;
    String msg;


    Target(String msg, MyCountDownLatch doneSignal) {
        this.msg = msg;

        c1 = new Thread(new Target1("1",doneSignal));

        c2 = new Thread(new Target1("2",doneSignal));
    }

    @Override
    public void run() {
        System.out.println("Start of Target " + msg);
        for (int j = 0; j < 100000; j++) {
            for (int i = 0; i < 10000; i++) {
                if (i % 10000 == 0 && j % 10000 == 0) {
                    System.out.print(msg);
                }
            }
        }

        c1.start();

        c2.start();
//      try {
//          c1.join();
//          c2.join();
//      } catch (InterruptedException e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }
        System.out.println("End of Target " + msg);

    }

    public Thread getC1() {
        return c1;
    }

    public Thread getC2() {
        return c2;
    }
}

class Target1 implements Runnable {

    String msg;
    private MyCountDownLatch doneSignal;

    Target1(String msg, MyCountDownLatch doneSignal) {
        this.msg = msg;
        this.doneSignal=doneSignal;
    }

    @Override
    public void run() {
        System.out.println("Start of Target1 " + msg);
        for (int j = 0; j < 100000; j++) {
            for (int i = 0; i < 100000; i++) {
                if (i % 100000 == 0 && j % 10000 == 0) {
                    System.out.print(msg);
                }
            }
        }
        try {

            System.out.println("K");
            doneSignal.countDown();
            System.out.println("End of Target1 " + msg);
        } catch (IllegalMonitorStateException e) {
            System.out.println("\nIllegalMonitorStateException!! in " + msg
                    + "\n");
        }
    }
}

class MyCountDownLatch {
    private int waitersNum;

    public MyCountDownLatch(int waitersNum) {
        this.waitersNum=waitersNum;
    }

    public synchronized void countDown() {
        waitersNum--;
        if (waitersNum==0) {
            notifyAll();
        }
    }

    public synchronized void await() throws InterruptedException {
        wait();
    }       
}