wait()和notify()
- 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。
- 如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
- 如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
分析wait方法:
1) 哪个线程调用了wait方法
2) 调用的是哪个对象的wait方法
3) 该线程继续执行的条件: 调用wait方法的那个对象在其他线程中调用了他的notify方法
注意:
wait和notify必须用在同步锁内部, 脱离同步锁不能使用
wait方法和sleep不同, sleep是使当前线程休眠但是继续持有锁, 而wait是会释放当前锁, 而wait执行结束继续向下执行时需要重新获得对象锁才可以
使用wait的目的并不是为了释放当前线程占有对象的控制权, 而是为了等待当前线程继续执行时所需的资源, 所以wait方法所在的同步锁由需要哪个对象来获取资源决定, 如下1是需要通过自身获取资源, 则在自身的对象锁中使用wait方法, 如下2是需要stack对象获取资源, 则在stack对象锁中使用wait方法
1.在自身线程中释放占有的自身对象
@Override
public void run() {
while (!isShutdown) {
if (target != null) {
target.run();
}
try {
//空闲线程对象放入池中
pool.putThread(this);
//System.out.println(pool.getThreadCount());
// 线程执行完任务,会在wait处阻塞,直到 setTarget或者 shutdown 调用notifyAll
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
}
}
}
// 每当设置任务或关闭时会唤醒run方法
public synchronized void setTarget(Runnable r) {
this.target = r;
notifyAll();
}
2.在自身线程中释放占有的其他对象
public T getInstance() {
T t = null;
synchronized (stack) {
if (stack.size() > 0) {
t = stack.pop();
usedSize++;
} else if (usedSize < maxSize) {
try {
t = (T) Class.forName(classpath).newInstance();
usedSize++;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 当前要获取对象的线程等待,等待stack中有对象归还
else {
try {
System.out.println("dengdai");
stack.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 注意这里如果使用t = stack.pop()在线程调用多的情况下可能报错
t = getInstance();
}
}
return t;
}
public void returnInstance(T t) {
//对象归还时是否要对对象做初始化
synchronized(stack) {
stack.push(t);
usedSize--;
stack.notify();
}
}

浙公网安备 33010602011771号