lock锁

关于前面volatile 关键字的使用,我们会发现,t2监控到自己的情况之后,t1需要进行中断,然后等t2监控执行完成之后,才能继续执行,但是实际情况中,当并发量很大时候,我们会只想让t1发出一个通知,然后t1继续执行,不让t1产生中断,这样就需要我们加入lock锁:

下面是详细代码:

package com.SynchronizedExample;

import java.util.ArrayList;
import java.util.List;

public class ListAdd2 {

	private volatile static List<String> list = new ArrayList<String>();

	public void add() {
		list.add("zhangsan");
	}

	public int size() {
		return list.size();
	}

	public static void main(String[] args) {
		final ListAdd2 list2 = new ListAdd2();
		final Object lock = new Object();

		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				synchronized (lock) {

					for (int i = 0; i < 10; i++) {
						list2.add();
						System.out.println("当前线程:"
								+ Thread.currentThread().getName()
								+ "添加了一个元素..");
						try {
							Thread.sleep(200);
							if (list2.size() == 5) {
								System.out.println("已经发出通知..");
								lock.notify();
							}

						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}
		}, "t1");

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {

				synchronized (lock) {

					if (list.size() != 5) {
						try {
							lock.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}

					System.out.println("当前线程:"
							+ Thread.currentThread().getName() + "收到通知, 线程停止");
					throw new RuntimeException();
				}
			}
		}, "t2");

		t2.start();
		t1.start();

	}
}

注意,在这里,需要t2先执行,将锁的状态wait会释放锁,但是notify不释放,如果先执行t1,锁一直不会被释放,产生的结果就会是t1执行全部完成,然后t2进入等待状态,一直等待下去。

因此,需要先执行t2,将整个锁状态处于wait之下,然后执行t1,当t1执行到5的时候,向t2发出通知,t1继续进行,产生的结果是:

lock锁

这样的结果,我们是做到了不影响t1 的执行,但是却有着不能实时监控缺陷,为了弥补这一缺陷,进一步参考下节:

CountDownLatch的使用。