zoukankan      html  css  js  c++  java
  • 线程之Thread

    如何创建一个线程并启动

            // 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
    • 线程inheritableThreadLocals继承自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:
             * <ul>
             *   <li>{@link Object#wait() Object.wait} with no timeout</li>
             *   <li>{@link #join() Thread.join} with no timeout</li>
             *   <li>{@link LockSupport#park() LockSupport.park}</li>
             * </ul>
             *
             * <p>A thread in the waiting state is waiting for another thread to
             * perform a particular action.
             *
             * For example, a thread that has called <tt>Object.wait()</tt>
             * on an object is waiting for another thread to call
             * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
             * that object. A thread that has called <tt>Thread.join()</tt>
             * 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:
             * <ul>
             *   <li>{@link #sleep Thread.sleep}</li>
             *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
             *   <li>{@link #join(long) Thread.join} with timeout</li>
             *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
             *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
             * </ul>
             */
            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则交给ThreadGroup处理
    • 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

    • 会引发死锁,避免使用

    • 线程挂起恢复使用sleep、join或者Object的wait、notify等实现

    线程join()方法

    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;
    
    • inheritableThreadLocals在构造方法里介绍了

    • ThreadLocal

        void createMap(Thread t, T firstValue) {
            t.threadLocals = new ThreadLocalMap(this, firstValue);
        }
    
    • 创建一个Map,赋值给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对象为key,对map进行操作
    • 看懂上面代码的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改成自己业务域名称
  • 相关阅读:
    杨辉三角
    手动实现md5加密
    戳气球
    重构字符串
    四数相加 II
    背包问题 II
    组合总和 IV
    背包问题 V
    背包问题
    Win 10安装Python及环境变量配置
  • 原文地址:https://www.cnblogs.com/zby9527/p/13143262.html
Copyright © 2011-2022 走看看