멀티 스레딩 학습 요약 (4 개)

ThreadLocal를 及 InheritableThreadLocal

1.의 ThreadLocal은 무엇인가?

간단히 말해서, 다음 JDK ThreadLocal 변수를 유지하여, 독립 변수의 사본을 제공하기 위해 각각의 스레드 ThreadLocal 변수를 사용하므로, 각 스레드는 독립적으로 다른 복사본에 영향을주지 않고 변화 할 스레드는 사본을 해당.

코드 보여줍니다

package com.my.thread;
   public class ThreadDemo2 {
       private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
           @Override
           public Integer initialValue() {
               return 0;
           }
       };
       static class ThreadDemo implements Runnable {
           @Override
           public void run() {
               for (int i = 0; i < 1000; i++) {
                   threadLocal.set(threadLocal.get() + 1);
               }
               System.out.println("thread :" + Thread.currentThread().getId() + " is" + threadLocal.get());
           }
       }
       public static void main(String[] args) {
           for (int i = 0; i < 10; i++) {
               new Thread(new ThreadDemo()).start();
           }
       }
   }
结果:
    thread :11 is1000
    thread :12 is1000
    thread :13 is1000
    thread :14 is1000
    thread :17 is1000
    thread :16 is1000
    thread :15 is1000
    thread :18 is1000
    thread :19 is1000
    thread :20 is1000

위의 결과에서 알 수있는 바와 같이, 모든 작업의 ​​출력은 스레드간에 영향을받지 않습니다. 더 공유 속성을 혼동 1000 작전 지침을 발생하지 않기 때문에.

(코드)의 ThreadLocal 원리 분석

ThreadLocal.ThreadLocalMap threadLocals = null;
        protected T initialValue() {
            return null;
        }
        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
        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();
        }
        private T setInitialValue() {
            T value = initialValue();
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
            return value;
        }
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
        ThreadLocalMap getMap(Thread t) {
           return t.threadLocals;
        }

개요

우리의 ThreadLocal을 사용하여 처음부터, 당신은 초기 값에 할당 된로 초기 () 메소드를 오버라이드 (override) 할 수 있습니다.
1. 메소드는 우선 설정 값 (T 값)을 설정하기 위해 호출해야하는 경우, 먼저 현재의 thread를 얻을하여 getMap (t)를 사용합니다 개체의 컬렉션을 ThreadLocalMap.
심판이 만들어지고 createMap (스레드 t, T firstValue) 널에 의해 할당됩니다.
, 설명은 ThreadLocalMap 수집하고있다하지 null의 경우, 직접 컬렉션에 추가 할 수 있습니다.
2. 첫 번째 전화를받을 경우 () 메소드는, ThreadLocalMap 현재 스레드 개체의 컬렉션을 가져옵니다하여 getMap (t)를 이동합니다.
그렇지 않으면 ThreadLocalMap 수집이 null에서, 그것을 얻을.
널, 그것은 setInitialValue () 메소드와 createMap에 의해 (스레드 t를 실행하는 경우 , T firstValue)를 생성하고 할당.

때 여기에, 그들은 그것을 이해해야합니다. 우리는 정의를 객체의 ThreadLocal 때, ThreadLocalMap 스레드에 대한 컬렉션을 만들지 않습니다.하지만 통화 얻을 ()을 판단하기 위해 만든 설정 방법.
그래서 각 스레드입니다 ThreadLocalMap는 자신의 사용에 대한 스레드의 고유 한 집합이 있습니다.

그런 다음 나사 끝은 처리하는 방법을 때?

private void exit() {
            if (group != null) {
                group.threadTerminated(this);
                group = null;
            }
            target = null;
            threadLocals = null;
            inheritableThreadLocals = null;
            inheritedAccessControlContext = null;
            blocker = null;
            uncaughtExceptionHandler = null;
        }

스레드의 끝이 호출하는 경우, 위의에서 볼 수있는 출구 () 메소드가 ThreadLocals을 = 널 (null) ;. 다음 ThreadLocalMap 컬렉션 파괴를 정리 와서 GC 기다리고 null 참조가 될 것입니다. 수행
이러한 치료는 아무 문제가 없었지만, 스레드 수영장 내부 동일하지 않습니다.

    package com.my.thread;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    public class ThreadLocalTest {

    	//创建一个Integer本地线程变量
    	private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
    		@Override
    		public Integer initialValue() {
    			return 0;
    		}
    	};
    	static class ThreadDemo implements Runnable {
    		@Override
    		public void run() {
    			for (int i = 0; i < 1000; i++) {
    				threadLocal.set(threadLocal.get() + 1);
    			}
    			System.out.println("thread :" + Thread.currentThread().getId() + " is" + threadLocal.get());
    			//threadLocal.remove();
    		}
    	}
    	public static void main(String[] args) {
    		ExecutorService executorService= Executors.newFixedThreadPool(5);
    		for (int i = 0; i < 10; i++) {
    			executorService.submit(new Thread(new ThreadDemo()));
    		}
    	}

    }

结果:
    thread :12 is1000
    thread :16 is1000
    thread :18 is1000
    thread :16 is2000
    thread :16 is3000
    thread :16 is4000
    thread :18 is2000
    thread :12 is2000
    thread :14 is1000
    thread :20 is1000

스레드를 축적하는 동안 스레드 풀에서 스레드 실행 살해하지,하지만. 다음 작업을 기다리고 스레드 시간에게 반환하기 때문에, 볼 수 있습니다.이는
우리가 //threadLocal.remove 때 (); 참고 개봉 후, 아래와 같은 결과.

结果:
       thread :14 is1000
       thread :14 is1000
       thread :14 is1000
       thread :14 is1000
       thread :12 is1000
       thread :14 is1000
       thread :12 is1000
       thread :16 is1000
       thread :18 is1000
       thread :20 is1000

우리는 결과는 지금의 ThreadLocal을 사용하여 스레드 풀에서의 ThreadLocal가 한 값으로, 일반적으로 사용하는 수 사용 후 비워 1000입니다 볼 수 있습니다.

2.InheritableThreadLocal

왜이 InheritableThreadLocal을 사용합니까?

첫째, ThreadLocal를 우리는 스레드를 스레드의 B를 시작하면 작업을 수행 할 수 있습니다.의 현장의 요구에 대해 이야기하자, 그러나 우리는 할 수있는 스레드의 필요성이 시간에 스레드 B에서의 ThreadLocal 스레드의 일부 값을 사용해야합니다 B는 스레드에 전달된다.

코드 장면을 보여줍니다

package com.my.thread;
public class ThreadLocalTest1 {
        private static  InheritableThreadLocal<Integer> inheritableThreadLocal = new  InheritableThreadLocal<Integer>();
        static class ThreadDemo implements Runnable {
        		@Override
        		public void run() {
        			for (int i = 0; i < 1000; i++) {
        				inheritableThreadLocal.set(inheritableThreadLocal.get() + 1);
        			}
        			System.out.println("thread :" + Thread.currentThread().getId() + " is" + inheritableThreadLocal.get());
        		}
        	}
        	public static void main(String[] args) {
        		inheritableThreadLocal.set(24);
        		for (int i = 0; i < 10; i++) {
        			new Thread(new ThreadDemo()).start();
        		}
        	}
        }
结果:
    thread :12 is1024
    thread :11 is1024
    thread :13 is1024
    thread :14 is1024
    thread :17 is1024
    thread :18 is1024
    thread :19 is1024
    thread :20 is1024
    thread :15 is1024
    thread :16 is1024

위의에서 볼 수있는 메인 스레드에서 (24)는 자식 스레드로 전달됩니다. 마지막으로 인쇄 (1024)

InheritableThreadLocal 원리 분석

InheritableThreadLocal 소스 코드 :

    public class InheritableThreadLocal<T> extends ThreadLocal<T> {
        protected T childValue(T parentValue) {
            return parentValue;
        }

        ThreadLocalMap getMap(Thread t) {
            return t.inheritableThreadLocals;
        }

        void createMap(Thread t, T firstValue) {
            t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
        }
    }

코드의 Thread 클래스 부분 :

    public class Thread implements Runnable {
        private void init(ThreadGroup g, Runnable target, String name,
                              long stackSize, AccessControlContext acc) {
                if (name == null) {
                    throw new NullPointerException("name cannot be null");
                }

                this.name = name.toCharArray();

                Thread parent = currentThread();
                SecurityManager security = System.getSecurityManager();
                if (g == null) {
                    /* Determine if it's an applet or not */

                    /* If there is a security manager, ask the security manager
                       what to do. */
                    if (security != null) {
                        g = security.getThreadGroup();
                    }

                    /* If the security doesn't have a strong opinion of the matter
                       use the parent thread group. */
                    if (g == null) {
                        g = parent.getThreadGroup();
                    }
                }

                /* checkAccess regardless of whether or not threadgroup is
                   explicitly passed in. */
                g.checkAccess();

                /*
                 * Do we have the required permissions?
                 */
                if (security != null) {
                    if (isCCLOverridden(getClass())) {
                        security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
                    }
                }

                g.addUnstarted();

                this.group = g;
                this.daemon = parent.isDaemon();
                this.priority = parent.getPriority();
                if (security == null || isCCLOverridden(parent.getClass()))
                    this.contextClassLoader = parent.getContextClassLoader();
                else
                    this.contextClassLoader = parent.contextClassLoader;
                this.inheritedAccessControlContext =
                        acc != null ? acc : AccessController.getContext();
                this.target = target;
                setPriority(priority);
                if (parent.inheritableThreadLocals != null)
                    this.inheritableThreadLocals =
                        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
                /* Stash the specified stack size in case the VM cares */
                this.stackSize = stackSize;

                /* Set thread ID */
                tid = nextThreadID();
            }

    }

간단한 요약 :

여기 InheritableThreadLocal 실제로 ThreadLocal를 상속을 참조하고,하여 getMap (스레드 t)와 createMap (스레드 t, T firstValue)와 세 가지 방법 childValue가 (T PARENTVALUE)를 다시 작성할 수 있습니다. 값이지도 세트에 할당하는 변수 inheritableThreadLocals 스레드입니다.
: 우리는 스레드의 소스 코드를 볼 때, 우리는 방법) 초기화 중 하나를 (찾을 수
, 스레드 부모 = currentThread ()
this.inheritableThreadLocals = ThreadLocal.createInheritedMap (parent.inheritableThreadLocals가)
여기를 참조 난 당신이 이해 생각 그것은 일의 방법에 대해 설명합니다.

간단하게 우리가 InheritableThreadLocal를 사용할 때, 넣어. ThreadLocal를하고 생성 및 초기화 같은. 그냥 완료 스레드 자식 스레드를 사용, 현재 부모 스레드 inheritableThreadLocals 아이 스레드에 전송합니다.이 자식 스레드에서 부모 스레드를 사용합니다 데이터.

프로모터는 자식 스레드 inheritableThreadLocal 24 통과 할 때 등의 경우 전술 한 바와 같이, 값 (24)은, 메인 쓰레드에 메인 쓰레드 inheritableThreadLocal에 실을 제공한다. 그런 다음 아이 thread 그 inheritableThreadLocal (기존 24의 초기 값) 작업을 축적 않으며, 최종 1024를 얻을 수

추천

출처www.cnblogs.com/one-reader/p/11329675.html