thread
线程是一个进程中的任务执行最小单位,执行调度的单位,依托于进程存在。 线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈,是在建立线程时由系统分配的,主要用来保存线程内部所使用的数据,如线程执行函数中所定义的变量。
Java中的多线程是一种抢占机制而不是分时机制。抢占机制指的是有多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU。
线程的核心内部field:
private Runnable target;
target是thread的执行目标方法,在thread进行调度时执行
ThreadLocal.ThreadLocalMap threadLocals = null;
threadlocals是一个threadlocal内部数据结构threadlocalMap,是线程内部变量副本的数据,通过使用threadlocal的set方法进行对当前线程设置线程私有的变量副本,从而使多线程间使用同一变量时,通过线程副本使用,避免线程间共享变量的冲突问题。但该方法仅适用于多线程共享变量不需要同步的时候,因为各个线程之间的变量变化是不共享的!
threadlocal
threadlocal是一个线程间共享变量副本的资源操作类,通过对多线程设置threadlocalMap中的k-v映射,实现多线程间thread变量副本控制,使用拷贝线程私有副本方式来进行操作。
set方法设置当前线程使用的变量副本,get方法可以获取到当前线程使用的变量副本,通过对get获取到的资源操作,是操作的共享变量的副本,不会对共享变量带来影响!这样保证线程间的资源安全
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
map.set(this, value);
} else {
createMap(t, value);
}
}
threadlocal的set方法步骤
1.获取当前线程
2.使用getmap获取到当前线程的内部threadlocalMap变量。
3.如果线程内部的map没有初始化则初始化并设置k-v= (threadlocal,value)
4.如果map不为空,则设置k-v=(currentthread,value)
注意假如对同一个threadlocal进行过线程设置value,则再次操作会覆盖原来,也就是一个threadlocal只能维护一个共享变量,不适用多变量。若要共享多变量,则最好使用类/集合进行封装,或者是使用多个threadlocal进行设置值
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();
}
threadlocal内部的get方法,从当前线程的内部维护的threadlocalmap集合,然后查找k=当前threadlocal的对应value值
threadlocalMap
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table[i];
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
threadlocalMap内部维护的是一个k-v结构的链表集合,k=threadlocal<> ,因为threadlocalmap是在thread线程内部使用的,因此维护的是一个threadlocal设置的value的entry,通过对同一个threadlocal的get,set来获取对应的变量副本!