Java中的wait方法

以下的的代码都是从http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4的阅读而来。

1.wait抛出IllegalMonitorStateException异常,表示当前的线程没有获得w的锁

package thread;

public class WaitTest2 {
	static class Wait{
		public Wait() {
			//
		}
	}
	
	static Wait w = new Wait();
	
	public static void main(String[] args) throws InterruptedException {
		//throw java.lang.IllegalMonitorStateException
		//because current method main is not lock w
		w.wait();		
	}
}

2.wait抛出IllegalArgumentException异常,给wait所传的参数错误

package thread;

public class WaitTest2 {
	static class Wait{
		public Wait() {
			//
		}
	}
	
	static Wait w = new Wait();
	
	public static void main(String[] args) throws InterruptedException {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}		
		
		synchronized(w) {
			//throw exception 
			//java.lang.IllegalArgumentException: nanosecond timeout value out of range
			//w.wait(1, 1000000);
			
			//throw exception
			//java.lang.IllegalArgumentException: timeout value is negative
			w.wait(-1);
		}
	}
}

3.正常的使用wait

package thread;

public class WaitTest2 {
	static class Wait{
		public Wait() {
			//
		}
	}
	
	static Wait w = new Wait();
	
	static class MessageLoop implements Runnable {
		public void run() {
			synchronized(w) {
				System.out.println("I will be waiting. and release the monitor " +this);
				try {
					w.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("I wait finished. and get the monitor" + this);
			}
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread(new MessageLoop(), "Thread1");
		t1.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		synchronized(w) {
			System.out.println("I got the monitor, and will notify "+ Thread.currentThread());
			w.notify();			
			System.out.println("I have been notified. and will release the monitor "+ Thread.currentThread());
		}
	}
}


以下是屏幕输出:

I will be waiting. and release the monitor thread.WaitTest2$MessageLoop@6fbae5f5
I got the monitor, and will notify Thread[main,5,main]
I have been notified. and will release the monitor Thread[main,5,main]
I wait finished. and get the monitorthread.WaitTest2$MessageLoop@6fbae5f5


4.  If a thread is both notified and interrupted while waiting, it may either:
    return normally from wait, while still having a pending interrupt (in other words, a call to Thread.interrupted would return true)

    return from wait by throwing an InterruptedException

   如果线程同时收到notify和interrupt,它可能会:

   从wait正常返回,但是没有处理interrupt,这时,Thread.interrupted返回为真

   在wait时异常退出

package thread;

public class WaitTest2 {
	static class Wait{
		public Wait() {
			//
		}
	}
	
	static Wait w = new Wait();
	
	static class MessageLoop implements Runnable {
		public void run() {
			synchronized(w) {
				System.out.println("I will be waiting. and release the monitor " +this);
				try {
					w.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("I wait finished. and get the monitor " + this);
			}
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread(new MessageLoop(), "Thread1");
		t1.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		synchronized(w) {
			System.out.println("I got the monitor, and will notify "+ Thread.currentThread());
			t1.interrupt();
			w.notify();			
			System.out.println("I have been notified. and will release the monitor "+ Thread.currentThread());
		}
	}
}

屏幕的输出如下:

I will be waiting. and release the monitor thread.WaitTest2$MessageLoop@208c5a4f
I got the monitor, and will notify Thread[main,5,main]
I have been notified. and will release the monitor Thread[main,5,main]
I wait finished. and get the monitorthread.WaitTest2$MessageLoop@208c5a4f

这个是notify先到,所以没有处理interrupt.

I will be waiting. and release the monitor thread.WaitTest2$MessageLoop@574f7121
I got the monitor, and will notify Thread[main,5,main]
I have been notified. and will release the monitor Thread[main,5,main]
I wait finished. and get the monitor thread.WaitTest2$MessageLoop@574f7121
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at thread.WaitTest2$MessageLoop.run(WaitTest2.java:17)
    at java.lang.Thread.run(Thread.java:722)

这个interrupt先到,所以先处理interrupt


另外,我在第二种情况时,看到屏幕输出如下:

I will be waiting. and release the monitor thread.WaitTest2$MessageLoop@6fbae5f5
I got the monitor, and will notify Thread[main,5,main]
I have been notified. and will release the monitor Thread[main,5,main]
java.lang.InterruptedExceptionI wait finished. and get the monitor thread.WaitTest2$MessageLoop@6fbae5f5

    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at thread.WaitTest2$MessageLoop.run(WaitTest2.java:17)
    at java.lang.Thread.run(Thread.java:722)

所以又有另外一个问题,System.out.println是线程安全的吗?
http://stackoverflow.com/questions/9459657/synchronization-and-system-out-println这个链接说是线程安全的,

但是为什么会出现一个println的内容会在另一个e.printStackTrace()中呢。尽管printStackTrace()方法中同步了OutputStream。

如下:

    private void printStackTrace(PrintStreamOrWriter s) {
        // Guard against malicious overrides of Throwable.equals by
        // using a Set with identity equality semantics.
        Set<Throwable> dejaVu =
            Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
        dejaVu.add(this);

        synchronized (s.lock()) {
        ...
        }
    }

5.See http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4
For example, if a thread t is in the wait set for m, and then both an interrupt of t and a notification of m occur,
there must be an order over these events. If the interrupt is deemed to have occurred first,
then t will eventually return from wait by throwing InterruptedException, and some other thread in the wait set for m
(if any exist at the time of the notification) must receive the notification. If the notification is deemed to have occurred first,
then t will eventually return normally from wait with an interrupt still pending.

package thread;

public class WaitTest2 {
	static class Wait{
		public Wait() {
			//
		}
	}
	
	static Wait w = new Wait();
	
	static class MessageLoop implements Runnable {
		public void run() {
			synchronized(w) {
				System.out.println("I will be waiting. and release the monitor " +this);
				try {
					w.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("I wait finished. and get the monitor " + this);
			}
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread(new MessageLoop(), "Thread1");
		t1.start();
		
		Thread t2 = new Thread(new MessageLoop(), "Thread2");
		t2.start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		synchronized(w) {
			System.out.println("I got the monitor, and will notify "+ Thread.currentThread());
			t1.interrupt();
			w.notify();			
			System.out.println("I have been notified. and will release the monitor "+ Thread.currentThread());
		}
	}
}

屏幕输出如下:


I will be waiting. and release the monitor thread.WaitTest2$MessageLoop@2ab6994f 线程一
I will be waiting. and release the monitor thread.WaitTest2$MessageLoop@3a0b2771线程二
I got the monitor, and will notify Thread[main,5,main]
I have been notified. and will release the monitor Thread[main,5,main]
I wait finished. and get the monitor thread.WaitTest2$MessageLoop@3a0b2771 线程二正常结束
java.lang.InterruptedException
I wait finished. and get the monitor thread.WaitTest2$MessageLoop@2ab6994f 线程一抛出异常
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:503)
    at thread.WaitTest2$MessageLoop.run(WaitTest2.java:19)
    at java.lang.Thread.run(Thread.java:722)

这里是如果有多个线程在wait w变量,这时如果有一个线程先收到interrupt的话,它会抛出interrupt异常,

然后会将notify传递给别的线程,然它们去出来notify。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值