Mercurial > hg > Members > shoshi > TreeCMSv2
view src/treecms/tree/util/CopyOnWriteTreeMap.java @ 25:c1e7ec6b3d44
commit
author | Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 12 Jul 2011 14:39:35 +0900 |
parents | 68021f7091e1 |
children |
line wrap: on
line source
package treecms.tree.util; import java.io.IOException; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.Map; import java.util.Random; import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class CopyOnWriteTreeMap<K extends Comparable<K>,V> { private volatile TreeNode<K,V> m_read; private volatile TreeNode<K,V> m_write; private final Object m_writeLock; public static void main(String _args[]) throws InterruptedException, IOException { System.in.read(); final CopyOnWriteTreeMap<String,String> map = new CopyOnWriteTreeMap<String,String>(); //final Map<String,String> map = Collections.synchronizedMap(new TreeMap<String,String>()); final LinkedList<String> keys = new LinkedList<String>(); Random r = new Random(); for(int i = 0;i < 10000;i ++){ String str = Long.toHexString(r.nextLong()); keys.add(str); } ExecutorService service = Executors.newFixedThreadPool(5); Callable<Object> writer = new Callable<Object>(){ @Override public Object call() throws Exception { long mill = System.currentTimeMillis(); for(String str : keys){ map.put(str,str); } System.out.println("Writer :"+ (System.currentTimeMillis() - mill)); return null; } }; Callable<Object> reader = new Callable<Object>(){ @Override public Object call() throws Exception { long mill = System.currentTimeMillis(); for(String str : keys){ map.get(str); } System.out.println("Reader :"+ (System.currentTimeMillis() - mill)); return null; } }; service.submit(reader); service.submit(writer); service.submit(writer); service.submit(writer); service.submit(writer); service.submit(writer); service.shutdown(); service.awaitTermination(Long.MAX_VALUE,TimeUnit.DAYS); System.in.read(); } public CopyOnWriteTreeMap() { m_read = m_write = null; m_writeLock = new Object(); } public V get(K _key) { if(m_read == null){ return null; } TreeNode<K,V> tn = m_read; while(tn != null){ K key = tn.key(); int result = key.compareTo(_key); if(result == 0){ //find return tn.value(); }else if(result > 0){ //go right TreeNode<K,V> r = tn.getRight(); tn = r; }else{ //go left TreeNode<K,V> l = tn.getLeft(); tn = l; } } return null; } public void put(K _key,V _value) throws InterruptedException { TreeNode<K,V> cur; synchronized(m_writeLock){ if(m_write == null){ m_write = new TreeNode<K,V>(_key,_value); m_write.unlock(); m_read = m_write; return; } m_write = m_write.copy(); cur = m_write; } while(true){ K key = cur.key(); int result = key.compareTo(_key); if(result > 0){ TreeNode<K,V> r = cur.getRight(); if(r == null){ r = new TreeNode<K,V>(_key,_value); cur.setRight(r); r.unlock(); cur.unlock(); break; } TreeNode<K,V> cp = r.copy(); cur.setRight(cp); cur.unlock(); cur = cp; }else if(result < 0){ TreeNode<K,V> l = cur.getLeft(); if(l == null){ l = new TreeNode<K,V>(_key,_value); cur.setLeft(l); l.unlock(); cur.unlock(); break; } TreeNode<K,V> cp = l.copy(); cur.setLeft(cp); cur.unlock(); cur = cp; }else{ cur.setValue(_value); cur.unlock(); m_read = m_write; return; } } m_read = m_write; } private static class TreeNode<K,V> { TreeNode<K,V> m_left; TreeNode<K,V> m_right; private K m_key; private V m_value; private volatile boolean m_flag; private final CountDownLatch m_latch; public TreeNode(K _key,V _value) { this(_key,_value,null,null); } private TreeNode(K _key,V _value,TreeNode<K,V> _left,TreeNode<K,V> _right) { m_key = _key; m_value = _value; m_left = _left; m_right = _right; m_latch = new CountDownLatch(1); m_flag = true; } public K key() { return m_key; } public V value() { return m_value; } public void setValue(V _value) { m_value = _value; } public void setKey(K _key) { m_key = _key; } public void setLeft(TreeNode<K,V> _left) { m_left = _left; } public void setRight(TreeNode<K,V> _right) { m_right = _right; } public TreeNode<K,V> getLeft() { return m_left; } public TreeNode<K,V> getRight() { return m_right; } public void unlock() throws InterruptedException { m_flag = false; m_latch.countDown(); } public TreeNode<K,V> copy() throws InterruptedException { if(m_flag){ m_latch.await(); } return new TreeNode<K,V>(m_key,m_value,m_left,m_right); } } }