• sleep()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
* 根据系统计时器和调度程序的精度和准确性,使得当前的执行线程进入睡眠状态(暂时停止继续执行)达到指定的毫秒数。在这期间该线程不会失去任何所有权。
*/
public static native void sleep(long millis) throws InterruptedException;

sleep()是Thread类的静态方法。调用该方式使得当前线程进入指定毫秒数的睡眠状态,并且不会释放同步资源锁。sleep()需要catch InterruptedException,否则线程在被其他线程中执行对该线程的interrupt()方法,sleep()就会报InterruptedException 线程就会被终止。

  • wait()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
* 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.
* 导致当前线程去等待,直到其他线程触发
* java.lang.Object#notify()方法或者一个特定的时间值执
* 行过去(设置的执行时间完成)
* <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:
* 线程称为不可调度并处于休眠状态,直到一下四种状况发生:
* <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.
* 某些其他线程触发notify方法,对于当前对象和线程恰好被任
* 意选择为要唤醒的线程。
* <li>Some other thread invokes the {@code
* notifyAll} method for this
* object.
* 某些其他线程触发notifyAll方法针对当前对象
* <li>Some other thread {@linkplain
* Thread#interrupt() interrupts}
* thread <var>T</var>.
* 某些其他线程触发了interrupts方法。
* <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.
* 特定的时间大致过去。如果这个时间是0,则不考虑时间,线程
* 只能等待通知
* </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.
* 因此,从{@code wait}方法返回时,对象和线程{@code T}
* 的同步状态与调用{@code wait}方法时的状态完全相同。
* <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 (&lt;condition does not hold&gt;)
* 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.
* 如果当前线程被任何其他线程中断则将会抛出
* InterruptedException
* 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;
* 注意wait方法被放置在当前线程对于该独享的等待集中,解锁
* 仅针对该对象
* 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.
*有关线程可以成为监视器所有者的方式的描述,请参见{@codenotify}方法。
* @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()是Object类的方法.主要用来协调多线程对共享资源的存取。当线程调用wait()方法时,该线程就和对象放置在等待集(或叫等待池)中,同时释放对象锁,当满足一定条件等待结束时,唤醒当前在等待集中的该线程(此时该线程与其他线程一起争夺对象的同步权),从等待集中移除的方式有:
1.某些其他线程触发notify方法,对于当前对象和线程恰好被任意选择为要唤醒的线程;
2.某些其他线程触发notifyAll方法;
3.某些其他线程触发了interrupts方法;
4.设置的特定wait时间到了。如果这个时间是0,则不考虑时间,线程只能等待通知。

其他线程调用interrupts方法中断时如果当前对象正在被其他线程占用,那么InterruptedException会在对象锁定状态恢复后抛出
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
* Package: com.litchi.demo.java
* Date: 2020/5/12
* Desc: com.litchi.demo.java
*
* @author liujicheng
*/
class LockTest {
public static java.lang.Object resourceOne = new Object();

public static void main(String[] args) {

Thread threadA = new Thread(new RunnableA());
threadA.start();

Thread threadB = new Thread(new RunnableB(threadA));
threadB.start();
}


static class RunnableA implements Runnable {

@Override
public void run() {
synchronized (resourceOne) {
System.out.println("Thread A lock resourceOne" + TimeUtil.getTime(System.currentTimeMillis()));

try {
resourceOne.wait();
} catch (InterruptedException e) {
System.out.println("ThreadA:" + TimeUtil.getTime(System.currentTimeMillis()));
}
}
}
}

static class RunnableB implements Runnable {

Thread thread;
public RunnableB(Thread thread) {
this.thread = thread;
}

@Override
public void run() {
int i = 1 << 3;
while ((i = i >> 1) > 0) {
synchronized (resourceOne) {
System.out.println("Thread B lock resourceOne:" + TimeUtil.getTime(System.currentTimeMillis()));

if (i == 4) {
System.out.println("Thread B request interrupt threadA:" + TimeUtil.getTime(System.currentTimeMillis()));
thread.interrupt();
try {
java.lang.Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
try {
java.lang.Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}


}

}

}
}
}

运行结果:

这里可以看到catch内的执行是在Thread B线程释放锁resourceOne对象后抛出的。

  • 两者区别比较:

1.sleep()时Thread类的静态方法,wait()是Object类的方法;
2.sleep()只是让当前线程休眠,不会释放同步锁,资源会被持续占有,wait()会释放同步锁,会把线程放入对象的wait集合中;
3.sleep()可以在任何地方使用,wait()方法、notify()方法和notiftAll()方法用于协调多线程对共享数据的存取,所以只能在同步方法或者同步块中使用,否则抛出IllegalMonitorStateException;
4.sleep()必须传入时间,而wait()可以传,也可以不传,如果不传要通过otify()方法和notiftAll()方法唤醒。