• Thread源码分析--01


    ##start方法

    public synchronized void start() {
            /**
             * This method is not invoked for the main method thread or "system"
             * group threads created/set up by the VM. Any new functionality added
             * to this method in the future may have to also be added to the VM.
             *==
             ==* A zero status value corresponds to state "NEW".
             */
            if (threadStatus != 0)
                throw new IllegalThreadStateException();
    
            /* Notify the group that this thread is about to be started
             * so that it can be added to the group's list of threads
             * and the group's unstarted count can be decremented. */
            group.add(this);
    
            boolean started = false;
            try {
                start0();
                started = true;
            } finally {
                try {
                    if (!started) {
                        group.threadStartFailed(this);
                    }
                } catch (Throwable ignore) {
                    /* do nothing. If start0 threw a Throwable then
                      it will be passed up the call stack */
                }
            }
        }
    
    这一个是Thread中start()方法的源码,我们由源码可以看出,当Thread执行NEW方法时,threadstatus变为0,否则将会报IllegalThreadStateException错误,可以得出Thread不能start()两次及以上,否则同样会出现IllegalThreadStateException

    至于start0()这个方法,是一个native,我们后续在研究(毕竟没啥基础,大家见谅,我们一步一步的来)。


    Thread的构造函数

    Thread的构造函数一共有9个,下面我们来看一下源码:
        public Thread() {
            init(null, null, "Thread-" + nextThreadNum(), 0);
        }
    
        /**
         * Allocates a new {@code Thread} object. This constructor has the same
         * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
         * {@code (null, target, gname)}, where {@code gname} is a newly generated
         * name. Automatically generated names are of the form
         * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
         *
         * @param  target
         *         the object whose {@code run} method is invoked when this thread
         *         is started. If {@code null}, this classes {@code run} method does
         *         nothing.
         */
        public Thread(Runnable target) {
            init(null, target, "Thread-" + nextThreadNum(), 0);
        }
    
        /**
         * Creates a new Thread that inherits the given AccessControlContext.
         * This is not a public constructor.
         */
        public Thread(Runnable target, AccessControlContext acc) {
            init(null, target, "Thread-" + nextThreadNum(), 0, acc);
        }
        public Thread(ThreadGroup group, Runnable target) {
            init(group, target, "Thread-" + nextThreadNum(), 0);
        }
    
        /**
         * Allocates a new {@code Thread} object. This constructor has the same
         * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
         * {@code (null, null, name)}.
         *
         * @param   name
         *          the name of the new thread
         */
        public Thread(String name) {
            init(null, null, name, 0);
        }
    
        /**
         * Allocates a new {@code Thread} object. This constructor has the same
         * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
         * {@code (group, null, name)}.
         *
         * @param  group
         *         the thread group. If {@code null} and there is a security
         *         manager, the group is determined by {@linkplain
         *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
         *         If there is not a security manager or {@code
         *         SecurityManager.getThreadGroup()} returns {@code null}, the group
         *         is set to the current thread's thread group.
         *
         * @param  name
         *         the name of the new thread
         *
         * @throws  SecurityException
         *          if the current thread cannot create a thread in the specified
         *          thread group
         */
        public Thread(ThreadGroup group, String name) {
            init(group, null, name, 0);
        }
    
        /**
         * Allocates a new {@code Thread} object. This constructor has the same
         * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
         * {@code (null, target, name)}.
         *
         * @param  target
         *         the object whose {@code run} method is invoked when this thread
         *         is started. If {@code null}, this thread's run method is invoked.
         *
         * @param  name
         *         the name of the new thread
         */
        public Thread(Runnable target, String name) {
            init(null, target, name, 0);
        }
    
        /**
         * Allocates a new {@code Thread} object so that it has {@code target}
         * as its run object, has the specified {@code name} as its name,
         * and belongs to the thread group referred to by {@code group}.
         *
         * <p>If there is a security manager, its
         * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess}
         * method is invoked with the ThreadGroup as its argument.
         *
         * <p>In addition, its {@code checkPermission} method is invoked with
         * the {@code RuntimePermission("enableContextClassLoaderOverride")}
         * permission when invoked directly or indirectly by the constructor
         * of a subclass which overrides the {@code getContextClassLoader}
         * or {@code setContextClassLoader} methods.
         *
         * <p>The priority of the newly created thread is set equal to the
         * priority of the thread creating it, that is, the currently running
         * thread. The method {@linkplain #setPriority setPriority} may be
         * used to change the priority to a new value.
         *
         * <p>The newly created thread is initially marked as being a daemon
         * thread if and only if the thread creating it is currently marked
         * as a daemon thread. The method {@linkplain #setDaemon setDaemon}
         * may be used to change whether or not a thread is a daemon.
         *
         * @param  group
         *         the thread group. If {@code null} and there is a security
         *         manager, the group is determined by {@linkplain
         *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
         *         If there is not a security manager or {@code
         *         SecurityManager.getThreadGroup()} returns {@code null}, the group
         *         is set to the current thread's thread group.
         *
         * @param  target
         *         the object whose {@code run} method is invoked when this thread
         *         is started. If {@code null}, this thread's run method is invoked.
         *
         * @param  name
         *         the name of the new thread
         *
         * @throws  SecurityException
         *          if the current thread cannot create a thread in the specified
         *          thread group or cannot override the context class loader methods.
         */
        public Thread(ThreadGroup group, Runnable target, String name) {
            init(group, target, name, 0);
        }
    
        /**
         * Allocates a new {@code Thread} object so that it has {@code target}
         * as its run object, has the specified {@code name} as its name,
         * and belongs to the thread group referred to by {@code group}, and has
         * the specified <i>stack size</i>.
         *
         * <p>This constructor is identical to {@link
         * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact
         * that it allows the thread stack size to be specified.  The stack size
         * is the approximate number of bytes of address space that the virtual
         * machine is to allocate for this thread's stack.  <b>The effect of the
         * {@code stackSize} parameter, if any, is highly platform dependent.</b>
         *
         * <p>On some platforms, specifying a higher value for the
         * {@code stackSize} parameter may allow a thread to achieve greater
         * recursion depth before throwing a {@link StackOverflowError}.
         * Similarly, specifying a lower value may allow a greater number of
         * threads to exist concurrently without throwing an {@link
         * OutOfMemoryError} (or other internal error).  The details of
         * the relationship between the value of the <tt>stackSize</tt> parameter
         * and the maximum recursion depth and concurrency level are
         * platform-dependent.  <b>On some platforms, the value of the
         * {@code stackSize} parameter may have no effect whatsoever.</b>
         *
         * <p>The virtual machine is free to treat the {@code stackSize}
         * parameter as a suggestion.  If the specified value is unreasonably low
         * for the platform, the virtual machine may instead use some
         * platform-specific minimum value; if the specified value is unreasonably
         * high, the virtual machine may instead use some platform-specific
         * maximum.  Likewise, the virtual machine is free to round the specified
         * value up or down as it sees fit (or to ignore it completely).
         *
         * <p>Specifying a value of zero for the {@code stackSize} parameter will
         * cause this constructor to behave exactly like the
         * {@code Thread(ThreadGroup, Runnable, String)} constructor.
         *
         * <p><i>Due to the platform-dependent nature of the behavior of this
         * constructor, extreme care should be exercised in its use.
         * The thread stack size necessary to perform a given computation will
         * likely vary from one JRE implementation to another.  In light of this
         * variation, careful tuning of the stack size parameter may be required,
         * and the tuning may need to be repeated for each JRE implementation on
         * which an application is to run.</i>
         *
         * <p>Implementation note: Java platform implementers are encouraged to
         * document their implementation's behavior with respect to the
         * {@code stackSize} parameter.
         *
         *
         * @param  group
         *         the thread group. If {@code null} and there is a security
         *         manager, the group is determined by {@linkplain
         *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
         *         If there is not a security manager or {@code
         *         SecurityManager.getThreadGroup()} returns {@code null}, the group
         *         is set to the current thread's thread group.
         *
         * @param  target
         *         the object whose {@code run} method is invoked when this thread
         *         is started. If {@code null}, this thread's run method is invoked.
         *
         * @param  name
         *         the name of the new thread
         *
         * @param  stackSize
         *         the desired stack size for the new thread, or zero to indicate
         *         that this parameter is to be ignored.
         *
         * @throws  SecurityException
         *          if the current thread cannot create a thread in the specified
         *          thread group
         *
         * @since 1.4
         */
        public Thread(ThreadGroup group, Runnable target, String name,
                      long stackSize) {
            init(group, target, name, stackSize);
        }
    

    会发现他们其实都是用的同一个方法Init(),只是传入的数据不一样,同样看出Thread的默认命名规则:Thread-为前缀,后面加上线程的数。 我们来看一下Init()这个方法

            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();
        }
    
    
    • 由Thread parent = currentThread();可以看出,线程的默认父线程就是新建Thread对象的线程。
    • 由代码可知,Thread的默认ThreadGroup是系统默认的Thread Group,如果没有,则设为父线程的线程组。
    • Thread的默认优先级为父线程的优先级,最大为10.最小为1,默认为5
    • Thread默认的类加载器同样为父线程的类加载器
    • Thread的ID是递增的。
    请多指教
  • 相关阅读:
    判断语句和循环语句2.2比较运算符
    判断语句和循环语句2.5 if中使用else
    判断语句和循环语句2.1 True、False
    判断语句和循环语句2.9while循环
    判断语句和循环语句2.7 if嵌套
    判断语句和循环语句2.8应用:猜拳游戏
    判断语句和循环语句逻辑运算符
    K8S 搭建 Prometheus (一) 部署 nodeexporter, prometheusserver
    使用Hive运行Job程序报GC错误
    离线数仓(四)
  • 原文地址:https://www.cnblogs.com/love-xi/p/9794765.html
Copyright © 2020-2023  润新知