/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ staticclassEntryextendsWeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value;
public T get(){ 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(); }
3、ThreadLocal的数据结构
五、常见使用场景
1.存储用户Session
2.Spring使用ThreadLocal解决线程安全问题
六、ThreadLocal 内存泄露问题是怎么导致的?
ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。所以,如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉。
publicclassStaticProxyTest{ publicstaticvoidmain(String[] args){ //被代理的学生张三,他的班费上交有代理对象monitor(班长)完成 Person zhangsan = new Student("张三"); //生成代理对象,并将张三传给代理对象 Person monitor = new StudentsProxy(zhangsan); //班长代理上交班费 monitor.giveMoney(); } }
publicclassThreadDemoimplementsCallable<Integer> { @Override public Integer call()throws Exception { int i = 0; for(;i<100;i++) { System.out.println(Thread.currentThread().getName()+" "+i); } return i; }
publicstaticvoidmain(String[] args)throws ExecutionException, InterruptedException { ThreadDemo threadDemo = new ThreadDemo(); FutureTask<Integer> ft = new FutureTask<>(threadDemo); new Thread(ft).start(); System.out.println(ft.get());
A finite-state machine (FSM) or finite-state automaton (FSA, plural: automata), finite automaton, or simply a state machine, is a mathematical model of computation.
首先介绍一下动态主机配置协议(Dynamic Host Configuration,DHCP),DHCP允许主机自动获取(被分配)一个P地址。网络管理员能够配置DHCP,以使某给定主机每次与网络连接时能得到一个相同的P地址,或者某主机将被分配一个临时的IP地址(temporary IP address),每次与网络连接时该地址也许是不同的。
Morris (InOrder) traversal is a tree traversal algorithm that does not employ the use of recursion or a stack. In this traversal, links are created as successors and nodes are printed using these links. Finally, the changes are reverted back to restore the original tree.
Algorithm
Initialize the root as the current node curr.
While curr is notNULL, check if curr has a left child.
If curr does not have a left child, print curr and update it to point to the node on the right of curr.
Else, make curr the right child of the rightmost node in curr's left subtree.
Update curr to this left node.
Demo
Let’s take the binary tree given below and traverse it using Morris (InOrder) traversal.
4 is the root, so it is initialized as curr. 4 has a left child, so it is made the rightmost right child of it’s left subtree (the immediate predecessor to 4 in an InOrder traversal). Finally, 4 is made the right child of 3 and curr is set to 2.
The {2} above refers to 2 and all of its children. Now that the tree has a link back to 4, the traversal continues.
1 is printed because it has no left child and curr is returned to 2, which was made to be 1's right child in the previous iteration. On the next iteration, 2 has both children. However, the dual-condition of the loop makes it stop when it reaches itself; this is an indication that its left subtree has already been traversed. So, it prints itself and continues with its right subtree (3). 3 prints itself, and curr becomes 4 and goes through the same checking process that 2 did. It also realizes that its left subtree has been traversed and continues with the 5. The rest of the tree follows this same pattern.
publicstaticvoidmain(String args[]) { Tree tree = new Tree(); tree.root = new Node(4); tree.root.left_node = new Node(2); tree.root.right_node = new Node(5); tree.root.left_node.left_node = new Node(1); tree.root.left_node.right_node = new Node(3);