2011-12-02 68 views
8

任何人都可以给我一个很好的小例子,演示java中的wait()和notify()函数。我已经尝试了下面的一段代码,但没有显示出我的预期。在java中演示wait()和notify()方法的一个很好的小例子

public class WaitDemo { 
    int i = 10; 

    int display() { 
     System.out.println("Lexmark"); 
     i++; 
     return i; 
    } 
} 
public class ClassDemo1 extends Thread { 

    private WaitDemo wd = new WaitDemo(); 

    public static void main(String[] args) { 
     ClassDemo1 cd1 = new ClassDemo1(); 
     ClassDemo1 cd2 = new ClassDemo1(); 
     cd1.setName("Europe"); 
     cd2.setName("America"); 
     cd1.start(); 
     cd2.start(); 

    } 

    synchronized void display() { 
     System.out.println("Hello"); 
     notifyAll(); 
    } 

    public void run() { 

     synchronized (this) { 
      try { 
       { 
        notify(); 
        System.out.println("The thread is " + currentThread().getName()); 
        wait(); 
        System.out.println("The value is " + wd.display()); 
       } 
      } catch (InterruptedException e) { 

      } 

     } 
    } 
} 

的问题是,在类WaitDemo的方法是没有得到等待后执行,按我的想法SOP()应该执行。请帮我解决这个问题。

+6

这不就是Google的用途吗? – mre

+7

@Крысa:请记住,SO的目标之一是成为Google(和其他)搜索的热门。这是一个完全合理的问题。应该以一个例子来回答 - 在这里,在这里,不在其他地方 - 讨论(理想情况下)苏拉夫在上面出错的地方。 –

+2

这个程序的预期行为是什么? – GETah

回答

3

您的try区块中有两个大括号{。如果你删除了内部集合(它似乎没有做任何事情),这是否解决了这个问题?

有几个例子,所有这些例子演示使用。最后一个链接是一组可以帮助你的结果。如果您需要更具体的东西,请告诉我您的应用正在尝试做什么,并且我可以尝试找到更适合您情况的示例。

0

你的问题是,你正在创建Thread类的两个实例。因此,当wait()被调用时,它在两个不同的实例上,这两个实例都没有另一个争用监视器的线程,也没有另一个线程调用notifyAll()将线程从等待状态中唤醒。

因此,您开始的每个线程都将永远等待(或因为其他原因而中断)。

你想让多个线程访问同一个监视器,所以首先尝试编写代码中的问题实际上不是一个线程,而只是被一个线程使用。

@normalocity已经提供了多个示例的链接。

0

我刚刚更新了this answer以包含SCCE

工人在WorkerPauseManager上调用pauseIfNeeded。如果管理器在工作者线程调用pauseIfNeeded()时暂停,我们调用wait(),它告诉调用线程等待,直到另一个线程调用正在等待的对象的notify()或notifyAll()。当Swing Event Dispatch Thread调用管理器上的play()时,会发生这种情况,该管理器又调用notifyAll()。

请注意,您必须对要调用wait()或notify()的对象拥有同步锁定。由于WorkerPauseManager中的方法是同步的,所有同步的方法都在WorkerPauseManager本身上获得一个同步的锁。

import javax.swing.*; 
import java.awt.event.ActionEvent; 

/** 
* @author sbarnum 
*/ 
public class WorkerPauseManagerTest { 
    public static void main(String[] args) { 
     final WorkerPauseManager pauseManager = new WorkerPauseManager(); 
     new Worker("Worker 1", pauseManager).start(); 
     new Worker("Worker 2", pauseManager).start(); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JToggleButton playPauseButton = new JToggleButton(new AbstractAction("Pause") { 
        public void actionPerformed(final ActionEvent e) { 
         JToggleButton source = (JToggleButton) e.getSource(); 
         if (source.isSelected()) { 
          pauseManager.start(); 
          source.setText("Pause"); 
         } else { 
          pauseManager.pause(); 
          source.setText("Play"); 
         } 
        } 
       }); 
       playPauseButton.setSelected(true); // already running 
       JOptionPane.showMessageDialog(null, playPauseButton, "WorkerPauseManager Demo", JOptionPane.PLAIN_MESSAGE); 
       System.exit(0); 
      } 
     }); 

    } 

    private static class Worker extends Thread { 
     final String name; 
     final WorkerPauseManager pauseManager; 

     public Worker(final String name, final WorkerPauseManager pauseManager) { 
      this.name = name; 
      this.pauseManager = pauseManager; 
     } 

     @Override 
     public void run() { 
      while (!Thread.interrupted()) { 
       try { 
        pauseManager.pauseIfNeeded(); 
        System.out.println(name + " is running"); 
        Thread.sleep(1000L); 
       } catch (InterruptedException e) { 
        throw new RuntimeException(e); 
       } 
      } 
     } 
    } 

    public static final class WorkerPauseManager { 

     private boolean paused; 

     public synchronized void pauseIfNeeded() throws InterruptedException { 
      if (paused) wait(); 
     } 

     public synchronized void pause() { 
      this.paused = true; 
     } 

     public synchronized void start() { 
      this.paused = false; 
      notifyAll(); 
     } 
    } 
} 
-2
/* 
* the below program is like 
* tread t1 will first run , and it comes to "notify()" method 
* there are no threds waiting bcoz this is the first thread. 
* so it will not invoke any other threads. next step is "wait()" method 
*will be called and the thread t1 in waiting state. next stament 
* "System.out.println("The value is ..."+wd.display());" will not be executed 
* because thread t1 is in waiting state. 
* 
* thread t2 will run ,and it comes to "notify()" method ,there is already 
* thread t1 is in waiting state ,then it will be invoked.now thread t1 will 
* continue execution and it prints the statement "System.out.println("The value is ..."+wd.display())" 
* and thread t2 will be in waiting state now. 
* 
* if you uncomment "notifyAll()" method then, after t1 thread completes its execution 
*then immediately "notifyAll()" method will be called,by that time thread t2 is 
* already in waiting state , then thread t2 will be invoked and continues execution. 
*or 
* if any other threadds are in waiting state all those threads will be invoked. 
*/ 
package threadsex; 

/** 
* 
* @author MaheshM 
*/ 
/** 
* @param args the command line arguments 
*/ 
public class WaitNotifyNotifyAllDemo implements Runnable { 
    WaitDemo wd = new WaitDemo(); 

    public static void main(String[] args) { 
     WaitNotifyNotifyAllDemo cd1 = new WaitNotifyNotifyAllDemo(); 
     Thread t1 = new Thread(cd1); 
     t1.setName("mahi1"); 
     Thread t2 = new Thread(cd1); 
     t2.setName("mahi2"); 
     t1.start();   
     t2.start(); 
    } 

    @Override 
    public void run() { 
     synchronized (this) { 
      try { 

       System.out.println("The thread is=" + 
         Thread.currentThread().getName()); 
       notify(); 
       wait(); 
       System.out.println("The value is ..." + wd.display()); 
       //   notifyAll(); 

      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 
1
> Below is example of wait notify 1st customer is trying to withdrawal 
> money 2000 but account is having only 1000 Rs so wait for deposit, 
> once deposit is completed then customer will able to withdrawal 
> amount ..till deposit customer is waiting. 

package com.thread.example; 

class Cust{ 

    private int totalAmount=1000; 

    public synchronized void withdrwl(int amount){ 
     System.out.println("Total amount "+totalAmount +" withdrwling amount "+amount); 
     if(this.totalAmount<amount){ 
      System.out.println("not enogh amount..waiting for deposite.."); 
      try{wait();}catch(Exception e){} 
     } 
     this.totalAmount-=amount;  
     System.out.println("Withrawl successful..Remaining balance is "+totalAmount); 

    } 

    public synchronized void deposite(int amount){ 
     System.out.println("Depositing amount "+amount); 
     this.totalAmount+=amount; 
     System.out.println("deposit completed...and Now totalAmount is "+this.totalAmount); 
     notify(); 
    } 
} 

class Depo implements Runnable{ 
    Cust c; int depo; 
    Depo(Cust c, int depo){ 
     this.c=c; 
     this.depo=depo; 

    } 

    @Override 
    public void run() { 
    c.deposite(depo); 

    } 

} 
class Withdrawl implements Runnable{ 
    Cust c; int with; 
    Withdrawl(Cust c, int with){ 
     this.c=c; 
     this.with=with; 

    } 

    @Override 
    public void run() { 
    c.withdrwl(with); 

    } 

} 

public class MainClass { 

    public static void main(String[] args) { 
     Cust c = new Cust(); 
     Thread w = new Thread(new Withdrawl(c, 2000)); 
     Thread d= new Thread(new Depo(c, 1000)); 
     w.start(); 
     d.start(); 


    } 

} 
1

我创建两个线程一个用于打印奇数(OddThread),另一个是偶数(EvenThread)。在每个线程的run方法内部,我使用Print类的共享对象分别为Odd和EvenThread调用printOdd()和printEven()。我将Print static的共享对象设置为只有一个副本。现在在Print对象上同步我使用了一个布尔标志,这样当奇数线程打印奇数时,它将被发送到等待状态,同时通知偶线执行。逻辑的写入方式使得奇数线程始终首先打印奇数,因为该标志最初设置为false,从而阻止偶线程执行并将其发送到等待状态。

 package com.amardeep.test; 

     public class ThreadDemo { 
      // Shared object 
      static Print print = new Print(); 

      public static void main(String[] args) { 

       new Thread(new OddThread()).start(); 
       new Thread(new EvenThread()).start(); 

      } 
     } 

     class EvenThread implements Runnable { 

      @Override 
      public void run() { 
       ThreadDemo.print.printEven(); 

      } 

     } 

     class OddThread implements Runnable { 

      @Override 
      public void run() { 

       ThreadDemo.print.printOdd(); 
      } 

     } 

     class Print { 
      public volatile boolean flag = false; 

      public synchronized void printEven() { 

       for (int i = 1; i <= 10; i++) { 
        if (!flag) { 
         try { 
          wait(); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } else { 
         if (i % 2 == 0) { 
          System.out.println("from even " + i); 
          flag = false; 
          notifyAll(); 
         } 

        } 
       } 
      } 

      public synchronized void printOdd() { 
       for (int i = 1; i <= 10; i++) { 
        if (flag) { 
         try { 
          wait(); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } else { 
         if (i % 2 != 0) { 
          System.out.println("from odd " + i); 
          flag = true; 
          notifyAll(); 
         } 

        } 
       } 
      } 
     } 
    output:- 
    from odd 1 
    from even 2 
    from odd 3 
    from even 4 
    from odd 5 
    from even 6 
    from odd 7 
    from even 8 
    from odd 9 
    from even 10 
+0

你能解释一下你的答案吗?答案不应该只是代码... – Jan

0

什么等待方法不是,当一些螺纹通过锁定某些对象(我们称之为对象为“a”)所执行的同步块,则该同步块内时的线程中执行对象的等待方法“一个”像这样

A a = new A(); // some class object call "a" 
    synchronized (a){ 
    a.wait();//exceptions must be handled 
} 

那么一个对象会释放,而线程具有去等待状态,直到它已经从该状态释放。

和另一个线程现在可以使用一个对象,因为它是一个释放对象。因此,如果另一个线程锁定该对象,并从该对象执行的通知方法类似

a.notify() 

于是,一路上对象等待状态“A”可以从等待状态被释放线程的线程之一。当调用notifyAll时,所有线程对象都会从该状态释放。

相关问题