Mercurial > hg > Members > shoshi > TreeCMSv2
comparison src/treecms/tree/util/CopyOnWriteTreeMap2.java @ 25:c1e7ec6b3d44
commit
author | Shoshi TAMAKI <shoshi@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 12 Jul 2011 14:39:35 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
24:68021f7091e1 | 25:c1e7ec6b3d44 |
---|---|
1 package treecms.tree.util; | |
2 | |
3 import java.util.Collections; | |
4 import java.util.Comparator; | |
5 import java.util.LinkedList; | |
6 import java.util.Map; | |
7 import java.util.Random; | |
8 import java.util.TreeMap; | |
9 import java.util.concurrent.Callable; | |
10 import java.util.concurrent.ConcurrentLinkedQueue; | |
11 import java.util.concurrent.CountDownLatch; | |
12 import java.util.concurrent.ExecutorService; | |
13 import java.util.concurrent.Executors; | |
14 import java.util.concurrent.TimeUnit; | |
15 import java.util.concurrent.atomic.AtomicReference; | |
16 import java.util.concurrent.locks.ReentrantLock; | |
17 | |
18 public class CopyOnWriteTreeMap2<K extends Comparable<K>,V> | |
19 { | |
20 private volatile TreeNode<K,V> m_read; | |
21 private final AtomicReference<TreeNode<K,V>> m_write; | |
22 | |
23 public static void main(String _args[]) throws InterruptedException | |
24 { | |
25 final CopyOnWriteTreeMap<String,String> map = new CopyOnWriteTreeMap<String,String>(); | |
26 //final Map<String,String> map = Collections.synchronizedMap(new TreeMap<String,String>()); | |
27 //final CopyOnWriteTreeMap2<String,String> map = new CopyOnWriteTreeMap2<String,String>(); | |
28 final LinkedList<String> keys = new LinkedList<String>(); | |
29 | |
30 Random r = new Random(); | |
31 for(int i = 0;i < 5000;i ++){ | |
32 String str = Long.toHexString(r.nextLong()); | |
33 // map.put(str,str); | |
34 keys.add(str); | |
35 } | |
36 | |
37 ExecutorService service = Executors.newFixedThreadPool(5); | |
38 | |
39 Callable<Object> task = new Callable<Object>(){ | |
40 @Override | |
41 public Object call() throws Exception | |
42 { | |
43 long mill = System.currentTimeMillis(); | |
44 for(String str : keys){ | |
45 map.put(str,str); | |
46 } | |
47 System.out.println(System.currentTimeMillis() - mill); | |
48 | |
49 return null; | |
50 } | |
51 }; | |
52 | |
53 service.submit(task); | |
54 service.submit(task); | |
55 service.submit(task); | |
56 service.submit(task); | |
57 service.submit(task); | |
58 | |
59 service.shutdown(); | |
60 service.awaitTermination(Long.MAX_VALUE,TimeUnit.DAYS); | |
61 | |
62 for(String key : keys){ | |
63 String val = map.get(key); | |
64 if(!val.equals(key)){ | |
65 System.out.println("val("+key+") is ok"); | |
66 } | |
67 } | |
68 } | |
69 | |
70 public CopyOnWriteTreeMap2() | |
71 { | |
72 m_read = null; | |
73 m_write = new AtomicReference<TreeNode<K,V>>(); | |
74 } | |
75 | |
76 public V get(K _key) | |
77 { | |
78 if(m_read == null){ | |
79 return null; | |
80 } | |
81 | |
82 TreeNode<K,V> tn = m_read; | |
83 | |
84 while(tn != null){ | |
85 K key = tn.key(); | |
86 int result = key.compareTo(_key); | |
87 if(result == 0){ | |
88 //find | |
89 return tn.value(); | |
90 }else if(result > 0){ | |
91 //go right | |
92 TreeNode<K,V> r = tn.getRight(); | |
93 tn = r; | |
94 }else{ | |
95 //go left | |
96 TreeNode<K,V> l = tn.getLeft(); | |
97 tn = l; | |
98 } | |
99 } | |
100 | |
101 return null; | |
102 } | |
103 | |
104 public void put(K _key,V _value) throws InterruptedException | |
105 { | |
106 TreeNode<K,V> root; | |
107 TreeNode<K,V> cur; | |
108 while(true){ | |
109 root = m_write.get(); | |
110 if(root == null){ | |
111 root = new TreeNode<K,V>(_key,_value); | |
112 root.unlock(); | |
113 if(m_write.compareAndSet(null,root)){ | |
114 m_read = root; | |
115 return; | |
116 } | |
117 continue; | |
118 } | |
119 | |
120 cur = root.copy(); | |
121 if(m_write.compareAndSet(root,cur)){ | |
122 break; | |
123 } | |
124 } | |
125 | |
126 while(true){ | |
127 K key = cur.key(); | |
128 int result = key.compareTo(_key); | |
129 | |
130 if(result > 0){ | |
131 TreeNode<K,V> r = cur.getRight(); | |
132 if(r == null){ | |
133 r = new TreeNode<K,V>(_key,_value); | |
134 cur.setRight(r); | |
135 r.unlock(); | |
136 cur.unlock(); | |
137 break; | |
138 } | |
139 TreeNode<K,V> cp = r.copy(); | |
140 cur.setRight(cp); | |
141 cur.unlock(); | |
142 cur = cp; | |
143 | |
144 }else if(result < 0){ | |
145 TreeNode<K,V> l = cur.getLeft(); | |
146 if(l == null){ | |
147 l = new TreeNode<K,V>(_key,_value); | |
148 cur.setLeft(l); | |
149 l.unlock(); | |
150 cur.unlock(); | |
151 break; | |
152 } | |
153 TreeNode<K,V> cp = l.copy(); | |
154 cur.setLeft(cp); | |
155 cur.unlock(); | |
156 cur = cp; | |
157 }else{ | |
158 cur.setValue(_value); | |
159 cur.unlock(); | |
160 m_read = root; | |
161 return; | |
162 } | |
163 } | |
164 | |
165 m_read = root; | |
166 } | |
167 | |
168 private static class TreeNode<K,V> | |
169 { | |
170 TreeNode<K,V> m_left; | |
171 TreeNode<K,V> m_right; | |
172 | |
173 private K m_key; | |
174 private V m_value; | |
175 private volatile boolean m_flag; | |
176 private final CountDownLatch m_latch; | |
177 | |
178 public TreeNode(K _key,V _value) | |
179 { | |
180 this(_key,_value,null,null); | |
181 } | |
182 | |
183 private TreeNode(K _key,V _value,TreeNode<K,V> _left,TreeNode<K,V> _right) | |
184 { | |
185 m_key = _key; | |
186 m_value = _value; | |
187 m_left = _left; | |
188 m_right = _right; | |
189 m_latch = new CountDownLatch(1); | |
190 m_flag = true; | |
191 } | |
192 | |
193 public K key() | |
194 { | |
195 return m_key; | |
196 } | |
197 | |
198 public V value() | |
199 { | |
200 return m_value; | |
201 } | |
202 | |
203 public void setValue(V _value) | |
204 { | |
205 m_value = _value; | |
206 } | |
207 | |
208 public void setKey(K _key) | |
209 { | |
210 m_key = _key; | |
211 } | |
212 | |
213 public void setLeft(TreeNode<K,V> _left) | |
214 { | |
215 m_left = _left; | |
216 } | |
217 | |
218 public void setRight(TreeNode<K,V> _right) | |
219 { | |
220 m_right = _right; | |
221 } | |
222 | |
223 public TreeNode<K,V> getLeft() | |
224 { | |
225 return m_left; | |
226 } | |
227 | |
228 public TreeNode<K,V> getRight() | |
229 { | |
230 return m_right; | |
231 } | |
232 | |
233 public void unlock() throws InterruptedException | |
234 { | |
235 m_flag = false; | |
236 m_latch.countDown(); | |
237 } | |
238 | |
239 public TreeNode<K,V> copy() throws InterruptedException | |
240 { | |
241 if(m_flag){ | |
242 m_latch.await(); | |
243 } | |
244 return new TreeNode<K,V>(m_key,m_value,m_left,m_right); | |
245 } | |
246 } | |
247 } |