## 黄金分割数与斐波那契数列

• 斐波那契数列：1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
• 通项公式：假设F(n)为该数列的第n项（n ∈ N*），那么这句话可以写成如下形式：F(n) = F(n-1) + F(n-2)。

## 黄金分割数的应用

public static void main(String[] args) throws Exception {
//黄金分割数 * 2的32次方 = 2654435769 - 这个是无符号32位整数的黄金分割数对应的那个值
long c = (long) ((1L << 32) * (Math.sqrt(5) - 1) / 2);
System.out.println(c);
//强制转换为带符号为的32位整型，值为-1640531527
int i = (int) c;
System.out.println(i);
}


public class Main {

private static final int HASH_INCREMENT = 0x61c88647;

public static void main(String[] args) throws Exception {
hashCode(4);
hashCode(16);
hashCode(32);
}

private static void hashCode(int capacity) throws Exception {
int keyIndex;
for (int i = 0; i < capacity; i++) {
keyIndex = ((i + 1) * HASH_INCREMENT) & (capacity - 1);
System.out.print(keyIndex);
System.out.print(" ");
}
System.out.println();
}
}


3 2 1 0
7 14 5 12 3 10 1 8 15 6 13 4 11 2 9 0
7 14 21 28 3 10 17 24 31 6 13 20 27 2 9 16 23 30 5 12 19 26 1 8 15 22 29 4 11 18 25 0


This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID)

ThreadLocal由Java界的两个大师级的作者编写，Josh Bloch和Doug Lea。Josh Bloch是JDK5语言增强、Java集合(Collection)框架的创办人以及《Effective Java》系列的作者。Doug Lea是JUC(java.util.concurrent)包的作者，Java并发编程的泰斗。所以，ThreadLocal的源码十分值得学习。

ThreadLocal虽然叫线程本地(局部)变量，但是实际上它并不存放任何的信息，可以这样理解：它是线程(Thread)操作ThreadLocalMap中存放的变量的桥梁。它主要提供了初始化、set()get()remove()几个方法。这样说可能有点抽象，下面画个图说明一下在线程中使用ThreadLocal实例的set()get()方法的简单流程图。

public class Main {

public static void main(String[] args) throws Exception{
LOCAL.set("doge");
System.out.println(LOCAL.get());
}
}


//获取下一个ThreadLocal实例的哈希魔数
private final int threadLocalHashCode = nextHashCode();

//原子计数器，主要到它被定义为静态
private static AtomicInteger nextHashCode = new AtomicInteger();

//哈希魔数(增长数)，也是带符号的32位整型值黄金分割值的取正
private static final int HASH_INCREMENT = 0x61c88647;

//生成下一个哈希魔数
private static int nextHashCode() {
}


//t1中的threadLocalHashCode变量为0x61c88647


threadLocalHashCode是下面的ThreadLocalMap结构中使用的哈希算法的核心变量，对于每个ThreadLocal实例，它的threadLocalHashCode是唯一的。

ThreadLocal内部类ThreadLocalMap使用了默认修饰符，也就是包(包私有)可访问的。ThreadLocalMap内部定义了一个静态类Entry。我们重点看下ThreadLocalMap的源码，先看成员和结构部分：

/**
* 为了处理非常大(指的是值)和长时间的用途，哈希表的Key使用了弱引用(WeakReferences)。
* 引用的队列(弱引用)不再被使用的时候，对应的过期的条目就能通过主动删除移出哈希表。
*/

static class Entry extends WeakReference<ThreadLocal<?>> {

//这个是真正的存放的值
Object value;
super(k);
value = v;
}
}
//初始化容量，必须是2的幂次方
private static final int INITIAL_CAPACITY = 16;

//哈希(Entry)表，必须时扩容，长度必须为2的幂次方
private Entry[] table;

//哈希表中元素(Entry)的个数
private int size = 0;

//下一次需要扩容的阈值，默认值为0
private int threshold;

//设置下一次需要扩容的阈值，设置值为输入值len的三分之二
private void setThreshold(int len) {
threshold = len * 2 / 3;
}

// 以len为模增加i
private static int nextIndex(int i, int len) {
return ((i + 1 < len) ? i + 1 : 0);
}

// 以len为模减少i
private static int prevIndex(int i, int len) {
return ((i - 1 >= 0) ? i - 1 : len - 1);
}
}


// 注意threadLocalHashCode在每个新ThreadLocal实例的构造同时已经确定了
private final int threadLocalHashCode = nextHashCode();
private static AtomicInteger nextHashCode = new AtomicInteger();
private static final int HASH_INCREMENT = 0x61c88647;
private static int nextHashCode() {
}

// 通过Supplier去覆盖initialValue方法
public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
}

// 默认公有构造函数

}


ThreadLocalset()方法的源码如下:

public void set(T value) {
//设置值前总是获取当前线程实例
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

}

void createMap(Thread t, T firstValue) {
}


• 获取当前运行线程的实例。
• 通过线程实例获取线程实例成员threadLocals(ThreadLocalMap)，如果为null，则创建一个新的ThreadLocalMap实例赋值到threadLocals。

ThreadLocalget()方法的源码如下:

 public T get() {
//获取当前线程的实例
if (map != null) {
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T) e.value;
return result;
}
}
return setInitialValue();
}

private T setInitialValue() {
// 调用initialValue方法获取值
T value = initialValue();
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}

protected T initialValue() {
return null;
}


initialValue()方法默认返回null，如果ThreadLocal实例没有使用过set()方法直接使用get()方法，那么ThreadLocalMap中的此ThreadLocal为Key的项会把值设置为initialValue()方法的返回值。如果想改变这个逻辑可以对initialValue()方法进行覆盖。

ThreadLocalremove()方法的源码如下:

public void remove() {
if (m != null)
m.remove(this);
}


public class Thread implements Runnable {

}


• 1、大量地(静态)初始化ThreadLocal实例，初始化之后不再调用get()set()remove()方法。
• 2、初始化了大量的ThreadLocal，这些ThreadLocal中存放了容量大的Value，并且使用了这些ThreadLocal实例的线程一直处于活跃的状态。

ThreadLocal中一个设计亮点是ThreadLocalMap中的Entry结构的Key用到了弱引用。试想如果使用强引用，等于ThreadLocalMap中的所有数据都是与Thread的生命周期绑定，这样很容易出现因为大量线程持续活跃导致的内存泄漏。使用了弱引用的话，JVM触发GC回收弱引用后，ThreadLocal在下一次调用get()set()remove()方法就可以删除那些ThreadLocalMap中Key为null的值，起到了惰性删除释放内存的作用。

public class ThreadLocalMain {

public static void main(String[] args) throws Exception {
TL_1.set(1);
TL_1 = null;
System.gc();
}
}


• 每次使用完ThreadLocal实例，都调用它的remove()方法，清除Entry中的数据。

ThreadLocal线程本地变量是线程实例传递和存储共享变量的桥梁，真正的共享变量还是存放在线程实例本身的属性中。ThreadLocal里面的基本逻辑并不复杂，但是一旦涉及到性能影响、内存回收(弱引用)和惰性删除等环节，其实它考虑到的东西还是相对全面而且有效的。