/** * 该类继承了WeakReference是方便垃圾回收,在底层map扩容之前进行entry的回收, * 减少扩容的概率,提高性能 */ staticclassEntryextendsWeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value;
// Rehash until we encounter null Entry e; int i; // 从staleSlot开始向后扫描一段连续的entry for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) { ThreadLocal<?> k = e.get(); //如果遇到key为null,表示无效entry,进行清理. if (k == null) { e.value = null; tab[i] = null; size--; } else { //如果key不为null,计算索引 int h = k.threadLocalHashCode & (len - 1); /** * 计算出来的索引——h,与其现在所在位置的索引——i不一致,置空当前的table[i] * 从h开始向后线性探测到第一个空的slot,把当前的entry挪过去。 */ if (h != i) { tab[i] = null;
// Unlike Knuth 6.4 Algorithm R, we must scan until // null because multiple entries could have been stale. while (tab[h] != null) h = nextIndex(h, len); tab[h] = e; } } } //下一个为空的solt的索引。 return i; }
/** * 启发式的扫描清除,扫描次数由传入的参数n决定 * * @param i 从i向后开始扫描(不包括i,因为索引为i的Slot肯定为null) * * @param n 控制扫描次数,正常情况下为 log2(n) , * 如果找到了无效entry,会将n重置为table的长度len,进行段清除。 * * map.set()点用的时候传入的是元素个数,replaceStaleEntry()调用的时候传入的是table的长度len * * @return true if any stale entries have been removed. */ privatebooleancleanSomeSlots(int i, int n){ boolean removed = false; Entry[] tab = table; int len = tab.length; do { i = nextIndex(i, len); Entry e = tab[i]; if (e != null && e.get() == null) { n = len; removed = true; i = expungeStaleEntry(i); } } while ( (n >>>= 1) != 0); return removed; }
/** * Re-pack and/or re-size the table. First scan the entire * table removing stale entries. If this doesn't sufficiently * shrink the size of the table, double the table size. */ privatevoidrehash(){ //全清理 expungeStaleEntries();
public T get(){ //同set方法类似获取对应线程中的ThreadLocalMap实例 Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } //为空返回初始化值 return setInitialValue(); } /** * 初始化设值的方法,可以被子类覆盖。 */ protected T initialValue(){ returnnull; }
private T setInitialValue(){ //获取初始化值,默认为null(如果没有子类进行覆盖) T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //不为空不用再初始化,直接调用set操作设值 if (map != null) map.set(this, value); else //第一次初始化,createMap在上面介绍set()的时候有介绍过。 createMap(t, value); return value; }
private ThreadLocal.ThreadLocalMap.Entry getEntry(ThreadLocal<?> key){ //根据key计算索引,获取entry int i = key.threadLocalHashCode & (table.length - 1); ThreadLocal.ThreadLocalMap.Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); }
/** * 通过直接计算出来的key找不到对于的value的时候适用这个方法. */ private ThreadLocal.ThreadLocalMap.Entry getEntryAfterMiss(ThreadLocal<?> key, int i, ThreadLocal.ThreadLocalMap.Entry e){ ThreadLocal.ThreadLocalMap.Entry[] tab = table; int len = tab.length;
while (e != null) { ThreadLocal<?> k = e.get(); if (k == key) return e; if (k == null) //清除无效的entry expungeStaleEntry(i); else //基于线性探测法向后扫描 i = nextIndex(i, len); e = tab[i]; } returnnull; }
publicstaticvoidmain(String[] args){ log.debug("This is debug"); log.info("This is info"); log.warn("This is warn"); log.error("This is error"); log.error("This is error", new RuntimeException("this is a exception")); } }
/** * 运算符:关系运算符 */ @Test publicvoidtest11(){ // 关系运算符(等于、不等于、小于、小于或等于、大于、大于或等于、instanceof、正则表达式) // lt (<) gt (>) le (<=) ge (>=) eq (==) ne (!=) div (/) mod (%) not (!) 可以在XML文档中替换相应的符号 // evaluates to true boolean flag = parser.parseExpression("2 == 2").getValue(Boolean.class); Assert.assertTrue(flag);
// evaluates to false flag = parser.parseExpression("2 < -5.0").getValue(Boolean.class); Assert.assertFalse(flag);
// evaluates to true flag = parser.parseExpression("'black' < 'block'").getValue(Boolean.class); Assert.assertTrue(flag);
// evaluates to false flag = parser.parseExpression( "'xyz' instanceof T(Integer)").getValue(Boolean.class); Assert.assertFalse(flag);
// evaluates to true flag = parser.parseExpression( "'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); Assert.assertTrue(flag);
//evaluates to false flag = parser.parseExpression( "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); Assert.assertFalse(flag); }
// evaluates to false boolean flagAnd = parser.parseExpression("true and false").getValue(Boolean.class); Assert.assertFalse(flagAnd);
// evaluates to true String expression = "isMember('尼古拉·特斯拉') and isMember('托马斯·阿尔瓦·爱迪生')"; flagAnd = parser.parseExpression(expression).getValue(context, Boolean.class); Assert.assertTrue(flagAnd);
// -- OR --
// evaluates to true boolean flagOr = parser.parseExpression("true or false").getValue(Boolean.class); Assert.assertTrue(flagOr);
// evaluates to true expression = "isMember('尼古拉·特斯拉') or isMember('托马斯·阿尔瓦·爱迪生')"; flagOr = parser.parseExpression(expression).getValue(context, Boolean.class); Assert.assertTrue(flagOr);
// -- NOT --
// evaluates to false boolean flagNot = parser.parseExpression("!true").getValue(Boolean.class); Assert.assertFalse(flagNot);
// -- AND and NOT -- expression = "isMember('尼古拉·特斯拉') and !isMember('托马斯·阿尔瓦·爱迪生')"; boolean flagAndNot = parser.parseExpression(expression).getValue(context, Boolean.class); Assert.assertFalse(flagAndNot); }
/** * 类类型表达式:使用"T(Type)"来表示java.lang.Class实例,"Type"必须是类全限定名,"java.lang"包除外,即该包下的类可以不指定包名; * 使用类类型表达式还可以进行访问类静态方法及类静态字段。 */ @Test publicvoidtest15(){ Inventor einstein = parser.parseExpression( "new com.littlefxc.examples.spel.Inventor('爱因斯坦', '德国')") .getValue(Inventor.class); Assert.assertEquals(new Inventor("爱因斯坦", "德国").getName(), einstein.getName());
context.setRootObject(society); //create new inventor instance within add method of List parser.parseExpression("Members.add(new com.littlefxc.examples.spel.Inventor('爱因斯坦', '德国'))").getValue(context); }
// 稍微复杂点 Inventor tesla = new Inventor("Nikola Tesla", "Serbian"); String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class); Assert.assertEquals("Nikola Tesla", name); // Nikola Tesla
tesla.setName(null); name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class); Assert.assertEquals("Elvis Presley", name); // Elvis Presley
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50722 Source Host : localhost:3306 Source Schema : batch Target Server Type : MySQL Target Server Version : 50722 File Encoding : 65001 Date: 31/01/2019 10:27:20 */