文章字数:431,阅读全文大约需要1分钟
一、等待和通知(Object方法)
1.1等待和通知
wait()
等待方
- 获取对象的锁
- 循环里判断条件是否满足,不满足调用
wait()
方法 - 满足执行业务
notify/notifyAll
通知方
- 获取对象锁
- 改变对象条件
- 通知所有等待对象的线程
wait()
用于休眠当前线程,需要调用同对象的notify()
或者notifyAll()
方法唤醒。wait()
、notify()
和notifyAll()
需要先获取到线程的锁,即synchronized
包裹。notify()
唤醒一个线程,notifyAll()
唤醒所有。建议都使用nofityAll()
方法,内部用while()
循环判断是否满足条件,不满足继续wait()
。否则会出现信号丢失情况。
1.2利用等待通知实现超时连接池
- 连接池
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// 保存链接的地方
private static LinkdList<Connection> pool = new LinkedList<>();
// 构造方法里初始化若干数量的数据库链接
public DBPool(int initalSize) {
if(initalSize > 0) {
for(int i = 0; i < initalSize; i++) {
pool.addLast(SqlConnectServer.fetchConnection());
}
}
}
// 获取线程,设置超时时间为mills,超时返回null。
public Connection fetchConn(long mills) {
synchronized(pool) {
// 不超时,等到有为止
if (mills < 0) {
while(pool.isEmpty()) {
pool.wait();
}
return pool.removeFirst();
} else{
// 什么时候超时
long overtime = System.currentTimeMillis() + mills;
// 剩余时间
long remain = mills;
// 池为空且还有等待时间
while(pool.isEmpty() && remain > 0) {
pool.wait(remain);
remain = overtime - System.currentTimeMillis();
}
Connection result = null;
if(!pool.isEmpty()) {
result = pool.removeFirst();
}
return result;
}
}
}
public void releseConn(Connection conn) {
if(conn != null) {
synchronized(pool) {
pool.addLast(conn);
pool.notifyAll();
}
}
}
二、join方法(Thread的)
功能
- 线程A执行了线程B的
join()
方法,则线程A必须等线程B执行之后才能继续自己的工作。
三、yield()、sleep()、wait()、notify()等对锁的影响
yield()
交出执行权,不释放持有的锁sleep()
休眠,不释放持有的锁wait()
方法执行前必须要持有锁,调用了wait()
方法之后,自动释放锁。被唤醒时自动持有锁notify()
方法执行前必须要持有锁,调用时本身不会释放锁。所以一般在synchroized
代码块最后。