进程与线程
线程的终止
Object
在Object类中,含有wait(),notify(),notifyAll()三个方法,它们主要是用于线程同步的。
在某一线程中调用wait()时,可以使用该线程进入等待状态,直到在别的地方调用了该Object的notify或者notifyAll()。
notifyAll()和notify()用于唤醒通过该Object对象调用wait()而进行等待状态的线程。只不过前者只是随机唤醒某一个,而后者是唤醒所有的。示例如下:
线程P:
- public class ProduceThread extends Thread {
- @Override
- public void run() {
- while (true) {
- synchronized (Main.lockObj) {
- while (Main.buf >= 1000) {
- try {
- Main.lockObj.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Main.buf++;
- System.out.println(getName() + "--操作了buf:" + Main.buf);
- Main.lockObj.notifyAll();
- }
- }
- }
- }
- public class CustomThread extends Thread {
- @Override
- public void run() {
- while (true) {
- synchronized (Main.lockObj) {
- while (Main.buf <= 0) {
- try {
- Main.lockObj.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Main.buf--;
- System.out.println(getName() + "--操作了buf:" + Main.buf);
- Main.lockObj.notifyAll();
- }
- }
- }
- }
在Main.lockObj.wait()外面仍旧套了一层while循环。这是为了保证在线程被唤醒时仍旧会进行判断,使线程只有在满足条件的情况下才会执行下面的代码。
假设将内层while循环换成if。有两个线程C,分别为c1,c2。假设某时刻c1正在执行,且此时buf为1。当c1执行完后,会唤醒p1与c2。并且系统调动的仍旧是c1,只不过c1在进入if块时进入wait状态,系统重新选择了p1。p1执行一次时,唤醒了wait状态的c1。只不过系统一直会执行p1直到p1的if判断成立,使p1进入wait。此时,系统调用c2(注意,c2执行一个循环后p1被唤醒,且c1仍旧处于唤醒状态,且代码停留在wait()处)。当c2将buf的值修改成0后,c2也会进入到wait状态。系统又选择了c1,c1对buf--操作时,buf就变成了-1(c2将buf的值变成了1),并且将c2唤醒。c2再次执行buf--后,buf会成为-2。
如果使用了while循环就不会出现上述情况,因为每一个线程被唤醒后的第一件事就是进行再次判断,保证了自己执行时是满足条件的。