스레드 Thread

12737 단어

어떻게 라인을 만들고 시작합니까

        // 1. Thread 
        Thread thread = new Thread();
        // 2. Thread start 
        thread.start();
  • 스레드가 시작되면 새로운 스레드에서 스레드 대상을 실행하는run 방법
  •     @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }
    
  • 따라서 새로운 라인에서 사용자 코드를 실행하려면 두 가지 방식이 있다.
  • Thread 클래스를 계승하고 run 방법을 다시 쓰는 방법
  • Thread 대상을 구성할 때 Runnable 대상을 전송하고 원래의 target 대상을 교체

  • Thread 상세 정보


    구조 방법

        public Thread() {
            init(null, null, "Thread-" + nextThreadNum(), 0);
        }
    
        public Thread(Runnable target) {
            init(null, target, "Thread-" + nextThreadNum(), 0);
        }
    
        Thread(Runnable target, AccessControlContext acc) {
            init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
        }
    
        public Thread(ThreadGroup group, Runnable target) {
            init(group, target, "Thread-" + nextThreadNum(), 0);
        }
    
        public Thread(String name) {
            init(null, null, name, 0);
        }
    
        public Thread(ThreadGroup group, String name) {
            init(group, null, name, 0);
        }
    
        public Thread(Runnable target, String name) {
            init(null, target, name, 0);
        }
    
        public Thread(ThreadGroup group, Runnable target, String name) {
            init(group, target, name, 0);
        }
    
        public Thread(ThreadGroup group, Runnable target, String name,
                      long stackSize) {
            init(group, target, name, stackSize);
        }
    
  • 모두 init 방법을 통해 라인을 구성하는 대상
  • group: 소속 스레드 그룹 지정
  • target: target 대상 바꾸기
  • name: 스레드 이름 지정
  • init 방법

    private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize, AccessControlContext acc,
                          boolean inheritThreadLocals) {
            if (name == null) {
                throw new NullPointerException("name cannot be null");
            }
    
            this.name = name;
    
            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 (inheritThreadLocals && 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();
        }
    
  • 생성된 스레드 대상의parent는 현재 스레드 대상을 만드는 스레드
  • 소속 스레드 그룹 일반인parent 소속 스레드 그룹
  • 스레드가 있을 때 수호 스레드가 기본적으로parent
  • 에서 계승되는지 여부
  • 라인 우선순위 기본값은parent
  • 에서 상속
  • 스레드 클래스 마운트는 기본적으로parent
  • 에서 상속됩니다.
  • 스레드 inheritable ThreadLocals는parent
  • 에서 계승

    스레드 상태

    public enum State {
            /**
             * Thread state for a thread which has not yet started.
             */
            NEW,
    
            /**
             * Thread state for a runnable thread.  A thread in the runnable
             * state is executing in the Java virtual machine but it may
             * be waiting for other resources from the operating system
             * such as processor.
             */
            RUNNABLE,
    
            /**
             * Thread state for a thread blocked waiting for a monitor lock.
             * A thread in the blocked state is waiting for a monitor lock
             * to enter a synchronized block/method or
             * reenter a synchronized block/method after calling
             * {@link Object#wait() Object.wait}.
             */
            BLOCKED,
    
            /**
             * Thread state for a waiting thread.
             * A thread is in the waiting state due to calling one of the
             * following methods:
             * 
      *
    • {@link Object#wait() Object.wait} with no timeout
    • *
    • {@link #join() Thread.join} with no timeout
    • *
    • {@link LockSupport#park() LockSupport.park}
    • *
    * *

    A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called Object.wait() * on an object is waiting for another thread to call * Object.notify() or Object.notifyAll() on * that object. A thread that has called Thread.join() * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: *

      *
    • {@link #sleep Thread.sleep}
    • *
    • {@link Object#wait(long) Object.wait} with timeout
    • *
    • {@link #join(long) Thread.join} with timeout
    • *
    • {@link LockSupport#parkNanos LockSupport.parkNanos}
    • *
    • {@link LockSupport#parkUntil LockSupport.parkUntil}
    • *
    */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }

    예외 처리

  • Thread
  •     private void dispatchUncaughtException(Throwable e) {
            getUncaughtExceptionHandler().uncaughtException(this, e);
        }
        public UncaughtExceptionHandler getUncaughtExceptionHandler() {
            return uncaughtExceptionHandler != null ?
                uncaughtExceptionHandler : group;
        }
    
    
  • ThreadGroup
  •     public void uncaughtException(Thread t, Throwable e) {
            if (parent != null) {
                parent.uncaughtException(t, e);
            } else {
                Thread.UncaughtExceptionHandler ueh =
                    Thread.getDefaultUncaughtExceptionHandler();
                if (ueh != null) {
                    ueh.uncaughtException(t, e);
                } else if (!(e instanceof ThreadDeath)) {
                    System.err.print("Exception in thread \""
                                     + t.getName() + "\" ");
                    e.printStackTrace(System.err);
                }
            }
        }
    
  • Thread 이상은 이상 프로세서가 처리하고 기본값null은 Thread Group 처리
  • 에 맡깁니다.
  • ThreadGroup은Thread를 실현했다.UncaughtExceptionHandler
  • Thread에 기본 예외 프로세서가 없음
  • 자체 처리 이상은 UncaughtExceptionHandler를 실현하고 setUncaughtExceptionHandler
  • 를 호출하면 됩니다.

    스레드 우선 순위

        /**
         * The minimum priority that a thread can have.
         */
        public final static int MIN_PRIORITY = 1;
    
       /**
         * The default priority that is assigned to a thread.
         */
        public final static int NORM_PRIORITY = 5;
    
        /**
         * The maximum priority that a thread can have.
         */
        public final static int MAX_PRIORITY = 10;
    
  • 반드시 우선순위 스케줄링 라인에 따라 엄격하게 스케줄링하는 것이 아니라 우선순위가 높고 스케줄링 기회가 높다고 말할 수 있다
  • 스레드 그룹

  • 대량 관리 스레드 세트
  • UncaughtExceptionHandler 구현, 기본 비정상 처리 제공
  • 스레드 인터럽트

        public void interrupt() {
            if (this != Thread.currentThread())
                checkAccess();
    
            synchronized (blockerLock) {
                Interruptible b = blocker;
                if (b != null) {
                    interrupt0();           // Just to set the interrupt flag
                    b.interrupt(this);
                    return;
                }
            }
            interrupt0();
        }
    
        public static boolean interrupted() {
            return currentThread().isInterrupted(true);
        }
    
        public boolean isInterrupted() {
            return isInterrupted(false);
        }
    
        private native boolean isInterrupted(boolean ClearInterrupted);
    
  • interrupt 설정 중단 표지
  • interrupted가 표지 위치를 중단하고 지울지 여부를 되돌려줍니다
  • isInterrupted가 표지 위치를 지우지 않고 중단되었는지 되돌려줍니다
  • Deprecated 메서드

  • stop、destroy、suspend、resume、countStackFrames
  • 사라짐을 유발하여 사용을 피한다
  • 스레드 마운트 복구 슬립,join 또는 Object의wait,notify 등 사용
  • 스레드join() 방법

  • see https://www.cnblogs.com/zby9527/p/7526606.html

  • ThreadLocal

  • Thread
  •     /* ThreadLocal values pertaining to this thread. This map is maintained
         * by the ThreadLocal class. */
        ThreadLocal.ThreadLocalMap threadLocals = null;
    
        /*
         * InheritableThreadLocal values pertaining to this thread. This map is
         * maintained by the InheritableThreadLocal class.
         */
        ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    
  • inheritable ThreadLocals가 구조방법에서 소개했다
  • ThreadLocal
  •     void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
    
  • Thread 객체에 값을 지정하는threadLocals 변수
  • 를 만듭니다.
        public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, 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();
        }
    
  • 현재 ThreadLocal 대상을 키로 하고 맵을 조작
  • 위 코드를 알아보는this
  • ThreadLocal에 신기한 숫자 0x61c88647, Why 0x61c88647
  • ThreadFactory

  • java.util.concurrent.ThreadFactory
  • package java.util.concurrent;
    
    public interface ThreadFactory {
    
        Thread newThread(Runnable r);
    }
    
    
  • java.util.concurrent.Executors.DefaultThreadFactory
  •     static class DefaultThreadFactory implements ThreadFactory {
            private static final AtomicInteger poolNumber = new AtomicInteger(1);
            private final ThreadGroup group;
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final String namePrefix;
    
            DefaultThreadFactory() {
                SecurityManager s = System.getSecurityManager();
                group = (s != null) ? s.getThreadGroup() :
                                      Thread.currentThread().getThreadGroup();
                namePrefix = "pool-" +
                              poolNumber.getAndIncrement() +
                             "-thread-";
            }
    
            public Thread newThread(Runnable r) {
                Thread t = new Thread(group, r,
                                      namePrefix + threadNumber.getAndIncrement(),
                                      0);
                if (t.isDaemon())
                    t.setDaemon(false);
                if (t.getPriority() != Thread.NORM_PRIORITY)
                    t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }
    
  • 라인 프로젝트를 베껴서namePrefix의pool을 자신의 업무 영역 이름으로 변경
  • 좋은 웹페이지 즐겨찾기