上一篇文章我们了解过了java有关线程的基本概念,有线程的属性,线程可能处于的状态,还有线程的两种创建的方式,最后还说了一个关键字synchronized,解决了高并发导致数据内容不一致问题,本篇文章就介绍线程的中断机制。
首先我们需要知道,java中的每个对象都是有内部对象锁的,其实每个java对象不止包含一个内部对象锁,还包含了一个等待队列和一个条件队列。
public synchronized void showName(){
************
}
这样的一个被synchronized关键字修饰的方法,如果已经有线程获得了该对象的锁,再有线程过来就会被阻塞并丢入等待队列中。
private int count;public synchronized void showName(){ if(count==0){
wait();
}
}public synchronized void setName(){ if(count==0){
notifyAll();
}
}
而在上述的代码段中,出现了两个方法:wait和notifyAll。这两个方法是成对出现的,wait主要作用是将当前线程阻塞并且置入条件队列上,notifyAll主要用于解放条件队列上的所有线程,使他们可以再次竞争处理机的调度以便运行。
小结一下,以上就比较了等待队列和条件队列的作用和区别。等待队列往往是因为想要申请的锁已经被别的线程占有了,需要置入等待队列等待占有锁的线程释放锁,然后接受处理机调度,被选中后方能获得锁并运行。而条件队列却是一个已经获得锁的线程在执行过程中发现自己继续运行的条件不满足(无法获得某些需要的资源),程序无法继续执行下去了,于是调用wait方法阻塞自己并释放外部对象锁,置入条件队列。
一旦占有某类资源的线程释放该资源之后,调用notifyAll方法释放所有在条件队列上等待的线程,使他们重新接受处理机的挑选。如果被处理机选中运行,就会从条件队列出队,占有对象锁,开始运行。需要注意的是:wait和notifyAll方法只能在synchronized修饰的代码块中调用,否则就会抛出异常。其实原因也很简单,wait必须指定将当前的线程挂在什么对象的条件队列上,notifAll必须被指定释放什么对象上的所有条件队列中的线程。synchronized关键字是针对某个对象加锁的,在其代码块中调用上述两种方法就默认操作