等待/唤醒机制。
1,同步。
2,wait,notify,notifyAll方法。
wait,notify,notifyAll这样的方法都属于监视器方法。
监视器你可以理解成就是那个锁。
这些方法用于操作持有该锁的线程。
一个锁对应一组监视器方法。
这些方法必须定义在同步中,并明确所在同步的锁。
简单说,这些方法必须要被锁对象调用。
---------------
生产者消费者,
如果只有一个生产者,一个消费者的,
那么可以通过 if判断标记,同时使用wait notify方法来完成等待唤醒。
当有多个生产者和消费者时,
如果通过这种方式,会出现,数据错误。 比如:一个生产者生产了两次,而只被消费一次。
问题产生的原因:本方被本方唤醒后,没有判断标记,也不清楚本方是否有执行,就进行了一次执行。
会导致之前的执行的有可能无效。
解决:必须让每次被唤醒的线程都判断一次标记。所以通过while循环来判断标记。
当循环判断标记后:发现,程序居然死锁了(程序没结束当无法继续执行。)
问题原因: 还是本方唤醒本方造成的,被唤醒的本方判断完标记后,有可能继续等待。导致了所有线程都等待。
解决:为了本方唤醒对象,而又没有直接方法完成,所以就使用过了notifyAll,将所有等待线程唤醒,
如果本方线程被唤醒,继续等,但是对方也被唤醒了,这就有了执行的机会。
所以多个生产者和消费者的解决方案就是 循环判断标记while,和notifyAll。
到了JDK1.5的时候,有了对锁和监视器的升级对象。
在java.util.concurrent.locks包中。
提供了两个对象 Lock Condition.
Lock接口替换了synchronized
同步函数或者同步代码块,对锁的操作是隐式的,并不直观。
而Lock将锁封装成了一个单独的对象,该对象具备获取锁和释放锁的方法。
也就是对锁的操作是显示。
Lock
lock():获取锁。
unlock():释放锁。
注意:锁本身也是一种资源。释放锁动作必须要执行。所以一般定义在finally代码块中。
Condition:以前监视器方法封装到了Object对象中,任意锁对象都可以使用。
现在将监视器方法封装到了Condition对象中。而Condition是通过Lock对象来获取的。
Lock对象可以绑定Condition.
监视器方法:
await();
signal():
signalAll():
这样就可以把原来的代码都用新对象来表示。
而且新对象提供了一个对多生产者消费者的解决方案。
Lock对象上,可以绑定多组监视器对象。
就可以实现本方只唤醒对象的操作。
public synchronized void set()
{
while(b)
wait();
code....;
b = true;
notifyAll();
}
public synchronized void out()
{
while(!b)
wait();
code....;
b = false;
notifyAll();
}
--
以上代码进行jdk1.5版本的改写。
//明确锁对象,而且明确监视器对象。和以前不同的是,
//Lock对象可以有多组监视器。
Lock lock = new ReentrantLock();
//生产者的监视器。
Condition con1 = lock.newCondition();
//消费者的监视器。
Condition con2 = lock.newCondition();
Thread-0 Thread-1
public void set()
{
lock.lock();
try
{
while(b)
con1.await();
code....;
b = true;
con2.signal();
}
finally
{
lock.unlock();
}
}
Thread-2 Thread-3
public void out()
{
lock.lock();
try
{
while(!b)
con2.await();
code....;
b = false;
con1.signal();
}
finally
{
lock.unlock();
}
}
-------------------
sleep和wait的区别:
sleep:释放执行权,不释放锁。
wait:释放执行权,释放锁。
---------
停止线程:
1,定义标记。控制住run中的循环。
2,如果线程冻结,无法执行标记,强制将其恢复到运行状态,interrupt():
该动作会放生异常。
守护线程:
setDaemon(boolean):当前台线程运行都结束了,后台线程无论是否执行完代码都会自动结束。
加入线程:
join():A线程执行到B线程的join方法是,A线程会释放执行权,等到B线程执行结束后,A在执行。
B线程执行时,A线程处于冻结状态。
|