wait、notify、notifyAll

标注的解释

/**
     * Wakes up a single thread that is waiting on this object's
     * monitor. If any threads are waiting on this object, one of them
     * is chosen to be awakened. The choice is arbitrary and occurs at
     * the discretion of the implementation. A thread waits on an object's
     * monitor by calling one of the {@code wait} methods.
	 
	 唤醒在这个对象的锁上等待的单个线程。如果有多个线程在这个对象上等待,
	 其中一个线程被选择唤醒。选择是任意的,并在执行的自由裁量权发生。线程通过调用 wait 方法在对象的锁上等待。
     * <p>
     * The awakened thread will not be able to proceed until the current
     * thread relinquishes the lock on this object. The awakened thread will
     * compete in the usual manner with any other threads that might be
     * actively competing to synchronize on this object; for example, the
     * awakened thread enjoys no reliable privilege or disadvantage in being
     * the next thread to lock this object.
     * <p>
		
	在当前线程放弃对该对象的锁定之前,唤醒线程将无法继续进行。
        唤醒线程将以通常的方式与任何可能在该对象上进行同步竞争的线程进行竞争;
        例如,唤醒线程在作为下一个线程来锁定该对象时不享有特权或也没有劣势。

     * This method should only be called by a thread that is the owner
     * of this object's monitor. A thread becomes the owner of the
     * object's monitor in one of three ways:
      
       此方法只能由 持有这个对象锁的线程 才能调用。 线程成为对象锁的所有者有以下3种方式:
          
          1、通过执行对象的 synchronized  实例方法
          2、通过执行对象 synchronized 代码块的主体
	      3、通过执行类的静态 synchronized 方法
	
     * <ul>
     * <li>By executing a synchronized instance method of that object.
     * <li>By executing the body of a {@code synchronized} statement
     *     that synchronizes on the object.
     * <li>For objects of type {@code Class,} by executing a
     *     synchronized static method of that class.
     * </ul>
     * <p>
     * Only one thread at a time can own an object's monitor.
	   每次只有一个线程才能获得对象的锁,对象只有一把锁
     *
     * @throws  IllegalMonitorStateException  if the current thread is not
     *               the owner of this object's monitor.
     * @see        java.lang.Object#notifyAll()
     * @see        java.lang.Object#wait()
     */
    public final native void notify();

    /**
     * Wakes up all threads that are waiting on this object's monitor. A
     * thread waits on an object's monitor by calling one of the
     * {@code wait} methods.
	 
	   唤醒所有在 对象锁上等待的 线程。  一个线程调用 对象的 wait 方法就变成等待 对象锁状态
     * <p>
     * The awakened threads will not be able to proceed until the current
     * thread relinquishes the lock on this object. The awakened threads
     * will compete in the usual manner with any other threads that might
     * be actively competing to synchronize on this object; for example,
     * the awakened threads enjoy no reliable privilege or disadvantage in
     * being the next thread to lock this object.
     * <p>
     * This method should only be called by a thread that is the owner
     * of this object's monitor. See the {@code notify} method for a
     * description of the ways in which a thread can become the owner of
     * a monitor.
     *
     * @throws  IllegalMonitorStateException  if the current thread is not
     *               the owner of this object's monitor.
     * @see        java.lang.Object#notify()
     * @see        java.lang.Object#wait()
     */
    public final native void notifyAll();

    /**
     * Causes the current thread to wait until either another thread invokes the
     * {@link java.lang.Object#notify()} method or the
     * {@link java.lang.Object#notifyAll()} method for this object, or a
     * specified amount of time has elapsed.
	 
	   使当前线程等待,直到另一个线程 执行了对象的 notify()、notifyAll() 方法。 或者指定的时间量已经过去
     * <p>
     * The current thread must own this object's monitor.
	   当前线程必须拥有 该对象的锁。
     * <p>
     * This method causes the current thread (call it <var>T</var>) to
     * place itself in the wait set for this object and then to relinquish
     * any and all synchronization claims on this object. Thread <var>T</var>
     * becomes disabled for thread scheduling purposes and lies dormant
     * until one of four things happens:
	 
	   此方法使当前线程将其自身放置在该对象的等待集中。并放弃对象的锁。直到发生下面四个方法才重新竞争锁:
	       
		    1、一些另外的线程调用 对象的notify方法
			2、一些另外的线程
			
     * <ul>
     * <li>Some other thread invokes the {@code notify} method for this
     * object and thread <var>T</var> happens to be arbitrarily chosen as
     * the thread to be awakened.
     * <li>Some other thread invokes the {@code notifyAll} method for this
     * object.
     * <li>Some other thread {@linkplain Thread#interrupt() interrupts}
     * thread <var>T</var>.
     * <li>The specified amount of real time has elapsed, more or less.  If
     * {@code timeout} is zero, however, then real time is not taken into
     * consideration and the thread simply waits until notified.
     * </ul>
     * The thread <var>T</var> is then removed from the wait set for this
     * object and re-enabled for thread scheduling. It then competes in the
     * usual manner with other threads for the right to synchronize on the
     * object; once it has gained control of the object, all its
     * synchronization claims on the object are restored to the status quo
     * ante - that is, to the situation as of the time that the {@code wait}
     * method was invoked. Thread <var>T</var> then returns from the
     * invocation of the {@code wait} method. Thus, on return from the
     * {@code wait} method, the synchronization state of the object and of
     * thread {@code T} is exactly as it was when the {@code wait} method
     * was invoked.
     * <p>
     * A thread can also wake up without being notified, interrupted, or
     * timing out, a so-called <i>spurious wakeup</i>.  While this will rarely
     * occur in practice, applications must guard against it by testing for
     * the condition that should have caused the thread to be awakened, and
     * continuing to wait if the condition is not satisfied.  In other words,
     * waits should always occur in loops, like this one:
     * <pre>
     *     synchronized (obj) {
     *         while (<condition does not hold>)
     *             obj.wait(timeout);
     *         ... // Perform action appropriate to condition
     *     }
     * </pre>
     * (For more information on this topic, see Section 3.2.3 in Doug Lea's
     * "Concurrent Programming in Java (Second Edition)" (Addison-Wesley,
     * 2000), or Item 50 in Joshua Bloch's "Effective Java Programming
     * Language Guide" (Addison-Wesley, 2001).
     *
     * <p>If the current thread is {@linkplain java.lang.Thread#interrupt()
     * interrupted} by any thread before or while it is waiting, then an
     * {@code InterruptedException} is thrown.  This exception is not
     * thrown until the lock status of this object has been restored as
     * described above.
     *
     * <p>
     * Note that the {@code wait} method, as it places the current thread
     * into the wait set for this object, unlocks only this object; any
     * other objects on which the current thread may be synchronized remain
     * locked while the thread waits.
     * <p>
     * This method should only be called by a thread that is the owner
     * of this object's monitor. See the {@code notify} method for a
     * description of the ways in which a thread can become the owner of
     * a monitor.
     *
     * @param      timeout   the maximum time to wait in milliseconds.
     * @throws  IllegalArgumentException      if the value of timeout is
     *               negative.
     * @throws  IllegalMonitorStateException  if the current thread is not
     *               the owner of the object's monitor.
     * @throws  InterruptedException if any thread interrupted the
     *             current thread before or while the current thread
     *             was waiting for a notification.  The <i>interrupted
     *             status</i> of the current thread is cleared when
     *             this exception is thrown.
     * @see        java.lang.Object#notify()
     * @see        java.lang.Object#notifyAll()
     */
    public final native void wait(long timeout) throws InterruptedException;


wait、notify例子

public class WaitNotifyDemo1 {
	
	private static DateFormat format = new SimpleDateFormat("HH:mm:ss");
	
	private static boolean flag = true;
	
	private static Object lock = new Object();
	
	public static void main(String[] args) {
		
		Thread wt = new Thread(new WaitThread(),"wt");
		Thread nt = new Thread(new NotifyThread(),"nt");
		wt.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		nt.start();
	}
	
	private static class WaitThread implements Runnable{

		@Override
		public void run() {
			
			synchronized (lock) {
				try {
					// 获得 对象 锁
					System.out.println(format.format(new Date())+"  "+Thread.currentThread().getName()+" is ruuning; flag = "+flag );
					
					//当前线程等待,  放弃 lock锁。等待唤醒
					lock.wait();
					
					System.out.println(format.format(new Date())+"  "+Thread.currentThread().getName()+" continue ruuning; flag = "+flag );
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
				
				flag = true;
				System.out.println(format.format(new Date())+"  "+Thread.currentThread().getName()+" prepare to give up lock; flag = "+flag );
			}
			
		}
		
	}
	
	
	
	private static class NotifyThread implements Runnable{

		@Override
		public void run() {
			synchronized (lock) {
				
				System.out.println(format.format(new Date())+"  "+Thread.currentThread().getName()+" is ruuning; flag = "+flag );
				flag = false;
				//唤醒处于等待状态其他线程
				lock.notify();
				System.out.println(format.format(new Date())+"  "+Thread.currentThread().getName()+" prepare to give up lock; flag = "+flag );
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(format.format(new Date())+"  "+Thread.currentThread().getName()+" have given up lock; flag = "+flag );
			
		}
		
	}

}


生产者和消费者

public class ProducerConsumerDemo {
	
	/**
	 * 仓库最大量
	 */
	private static Integer MAX_SIZE = 100;
	/**
	 * 仓库
	 */
	private static LinkedList list = new LinkedList();
	
	public static void main(String[] args) {
		
		//生产者生产
		Thread p1 = new Thread(new producer(20));
		Thread p2 = new Thread(new producer(20));
		Thread p3 = new Thread(new producer(20));
		Thread p4 = new Thread(new producer(20));
		Thread p5 = new Thread(new producer(20));
		Thread p6 = new Thread(new producer(100));
		
		
		//消费者消费
		Thread c1 = new Thread(new consumer(50));
		Thread c2 = new Thread(new consumer(30));
		Thread c3 = new Thread(new consumer(20));
		
		
		//执行
		c1.start();
		c2.start();
		c3.start();
		
		p1.start();
		p2.start();
		p3.start();
		p4.start();
		p5.start();
		//p6.start();
		
	}
	
	
	/**
	 * 生产者
	 * @author chenzhengwei
	 *
	 */
	private static class producer implements Runnable{
		
		/**
		 * 生产数量
		 */
		private Integer num;
		
		public producer(Integer num) {
			this.num = num;
		}

		@Override
		public void run() {
			
			synchronized (list) {
				
				/**
				 * 仓库容量不足
				 */
				while(list.size()+num > MAX_SIZE) {
					System.out.println("[仓库最大容量]:"+MAX_SIZE+"  [生产者要生产的数量]:"+num+"  [现有库存数量]:"+list.size()+"  仓库容量不足停止生产");
					
					try {
						list.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
				/**
				 * 生产者生产
				 */
				for(int i = 1; i <= num; i++) {
					list.add(new Object());
				}
				
				System.out.println("[仓库最大容量]:"+MAX_SIZE+"  [生产者已生产数量]:"+num+"  [现有仓库库存量]:"+list.size()+"  生产成功");
				
				/**
				 * 仓库还有库存,剩余库存,通知消费者消费或其他生产者生产
				 */
				list.notifyAll();
			}
			
		}
		
		
	}
	
	
	/**
	 * 消费者
	 * @author chenzhengwei
	 *
	 */
	private static class consumer implements Runnable {
		
		/**
		 * 消费数量
		 */
		private Integer num;
		
		public consumer(Integer num) {
			this.num = num;
		}

		@Override
		public void run() {
			
			synchronized (list) {
				
				while(list.size() < num) {
                    System.out.println("[仓库最大容量]:"+MAX_SIZE+"  [消费者要消费的数量]:"+num+"  [现有库存数量]:"+list.size()+"  库存数量不足无法消费");
					
					try {
						list.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				
				for(int i = 1; i <= num; i++) {
					list.remove();
				}
				
				System.out.println("[仓库最大容量]:"+MAX_SIZE+"  [消费者已消费数量]:"+num+"  [现有仓库库存量]:"+list.size()+"  消费成功");
				
				/**
				 * 仓库还有库存,剩余库存,通知生产者生产或其他消费者消费
				 */
				list.notifyAll();				
			}
			
		}
		
		
	}

}

猜你喜欢

转载自blog.csdn.net/SHIYUN123zw/article/details/80177144