`
chenzehe
  • 浏览: 532810 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

面试题——在多线程环境下如何保证一个List集合中的元素不超过15个

阅读更多

这是有一次去面试被问到的,当时只知道用synchronized来保证同步,但面试官说除了此方式的其它实现,现在写下它的各种实现:

1、JDK1.5之前的内置锁synchronized实现

 模仿JDK1.5之前同步集合SynchronizedList的实现,内部使用synchronized对一个对一个List的封装,如下代码:

/**
 * @description
 * 
 * @author chenzehe
 * @email hljuczh@163.com
 * @create 2013-2-22 下午05:03:43
 */
public class SyncList<E> implements List<E> {
	final Object	mutex;
	final List<E>	list;
	final int		fixSize;	
	public SyncList(List list, int fixSize) {
		super();
		mutex = this;
		this.list = list;
		this.fixSize = fixSize;
	}	
	@Override
	public boolean add(E e) {
		synchronized (mutex) {
			if (list.size() < fixSize) {
				System.out.println("add成功,size=" + list.size());
				return list.add(e);
			}
			else {
				System.out.println("大小已超过fixSize,不能再add...");
				return false;
			}
		}
		
	}	
	@Override
	public E remove(int index) {
		synchronized (mutex) {
			if (list.size() > 0) {
				System.out.println("删除成功...");
				return list.remove(index);
			}
			else {
				return null;
			}
		}
	}
        ......
}

 测试类,模拟几个线程对该集合进行操作:

/**
 * @description
 * 
 * @author chenzehe
 * @email hljuczh@163.com
 * @create 2013-2-22 下午05:49:40
 */
public class SyncListTest {	
	public static void main(String[] args) {
		int fixSize = 10;
		SyncList<Integer> syncList = new SyncList<Integer>(new ArrayList<Integer>(), fixSize);
		AddThread addThread = new AddThread(syncList);
		RemoveThread removeThread = new RemoveThread(syncList);
		new Thread(addThread).start();
		new Thread(addThread).start();
		new Thread(removeThread).start();
	}	
}

class AddThread implements Runnable {
	private SyncList<Integer>	syncList;
	
	public AddThread(SyncList<Integer> syncList) {
		this.syncList = syncList;
	}	
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			syncList.add(i);
			try {
				Thread.sleep(100);
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class RemoveThread implements Runnable {
	private SyncList<Integer>	syncList;
	
	public RemoveThread(SyncList<Integer> syncList) {
		this.syncList = syncList;
	}
	
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			syncList.remove(0);
			try {
				Thread.sleep(300);
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
}

 输出:

add成功,size=0
add成功,size=1
删除成功...
add成功,size=1
add成功,size=2
add成功,size=3
add成功,size=4
删除成功...
add成功,size=4
add成功,size=5
add成功,size=6
add成功,size=7
add成功,size=8
add成功,size=9
大小已超过fixSize,不能再add...
大小已超过fixSize,不能再add...
删除成功...
add成功,size=9
大小已超过fixSize,不能再add...
... 

 2、JDK1.5之前的显示锁,并使用Condition控制当集合中的元素达到最大时使线程等待,如下代码:

 

/**
 * @description
 * 
 * @author chenzehe
 * @email hljuczh@163.com
 * @create 2013-2-22 下午06:43:06
 */

public class ReentrantLockList<E> implements List<E> {
	final List<E>				list;
	final int					fixSize;
	
	private final ReadWriteLock	lock		= new ReentrantReadWriteLock();
	private final Lock			r			= lock.readLock();
	private final Lock			w			= lock.writeLock();
	final Condition				notFull		= w.newCondition();
	final Condition				notEmpty	= w.newCondition();
	
	public ReentrantLockList(List<E> list, int fixSize) {
		super();
		this.list = list;
		this.fixSize = fixSize;
	}
	
	@Override
	public boolean add(E e) {
		boolean addResult = false;
		w.lock();
		try {
			while (list.size() >= fixSize) {
				System.out.println("大小已超过fixSize不能再添加,在等待中...");
				notFull.await();// Causes the current thread to wait until it is signalled or interrupted
			}
			addResult = list.add(e);
			System.out.println("add成功,size=" + list.size());
			notEmpty.signal();// Wakes up one waiting thread
		}
		catch (InterruptedException e2) {
			e2.printStackTrace();
		}
		finally {
			w.unlock();
		}
		return addResult;
	}
	
	@Override
	public E remove(int index) {
		E removeResult = null;
		w.lock();
		try {
			while (list.size() < 1) {
				System.out.println("集合为空不能删除,在等待中...");
				notEmpty.await();// Causes the current thread to wait until it is signalled or interrupted
			}
			removeResult = list.remove(index);
			System.out.println("删除成功...");
			notFull.signal();// Wakes up one waiting thread
		}
		catch (InterruptedException e2) {
			e2.printStackTrace();
		}
		finally {
			w.unlock();
		}
		return removeResult;
		
	}
	......
}
 测试类模拟几个线程同时对该集体进行操作:

 

 

/**
 * @description
 * 
 * @author chenzehe
 * @email hljuczh@163.com
 * @create 2013-2-22 下午07:04:50
 */

public class ReentrantLockListTest {
	
	public static void main(String[] args) {
		int fixSize = 10;
		ReentrantLockList<Integer> reentrantLockList = new ReentrantLockList<Integer>(new ArrayList<Integer>(), fixSize);
		AddReentrantLockListThread addThread = new AddReentrantLockListThread(reentrantLockList);
		RemoveReentrantLockListThread removeThread = new RemoveReentrantLockListThread(reentrantLockList);
		new Thread(addThread).start();
		new Thread(addThread).start();
		new Thread(removeThread).start();		
	}
	
}

class AddReentrantLockListThread implements Runnable {
	private ReentrantLockList<Integer>	reentrantLockList;
	
	public AddReentrantLockListThread(ReentrantLockList<Integer> reentrantLockList) {
		this.reentrantLockList = reentrantLockList;
	}
	
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			reentrantLockList.add(i);
			try {
				Thread.sleep(100);
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class RemoveReentrantLockListThread implements Runnable {
	private ReentrantLockList<Integer>	reentrantLockList;
	
	public RemoveReentrantLockListThread(ReentrantLockList<Integer> reentrantLockList) {
		this.reentrantLockList = reentrantLockList;
	}
	
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			reentrantLockList.remove(0);
			try {
				Thread.sleep(300);
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
}
 

 

 输出结果:

 

集合为空不能删除,在等待中...
add成功,size=1
add成功,size=2
删除成功...
add成功,size=2
add成功,size=3
add成功,size=4
add成功,size=5
add成功,size=6
删除成功...
add成功,size=6
add成功,size=7
add成功,size=8
add成功,size=9
add成功,size=10
大小已超过fixSize不能再添加,在等待中...
删除成功...
add成功,size=10
大小已超过fixSize不能再添加,在等待中...
大小已超过fixSize不能再添加,在等待中...
删除成功...
add成功,size=10
大小已超过fixSize不能再添加,在等待中...
...
 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics