thread和threadlocal

2019-10-10  本文已影响0人  wifiLIu

thread

线程是一个进程中的任务执行最小单位,执行调度的单位,依托于进程存在。 线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈,是在建立线程时由系统分配的,主要用来保存线程内部所使用的数据,如线程执行函数中所定义的变量。

Java中的多线程是一种抢占机制而不是分时机制。抢占机制指的是有多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU。

线程的核心内部field:
private Runnable target; target是thread的执行目标方法,在thread进行调度时执行
ThreadLocal.ThreadLocalMap threadLocals = null; threadlocals是一个threadlocal内部数据结构threadlocalMap,是线程内部变量副本的数据,通过使用threadlocal的set方法进行对当前线程设置线程私有的变量副本,从而使多线程间使用同一变量时,通过线程副本使用,避免线程间共享变量的冲突问题。但该方法仅适用于多线程共享变量不需要同步的时候,因为各个线程之间的变量变化是不共享的!

threadlocal

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来获取对应的变量副本!

上一篇 下一篇

猜你喜欢

热点阅读