以下的的代码都是从
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。