【JMM】Thread源码分析之创建和启动线程

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

文章首发于:clawhub.club


可以通过继承Thread类,覆写run方法方式或者继承自Runnable接口创建一个线程。
Thread类也实现了Runnable接口:
此接口由注解@FunctionalInterface修饰,也就是可以使用lambda表达式,其中的run方法,如果直接调用,那就是普通的方法,如果通过现成的start()方法调用,
就会创建一个新的线程调用这个run()方法,即使用Java多线程特性。

    @FunctionalInterface
    public interface Runnable {
        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }

线程的创建

Thread类中,有好多个构造方法:

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(String name) {
        init(null, null, name, 0);
    }
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(ThreadGroup group, String name) {
        init(group, null, 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方法:
里面基本上都是native方法和初始化参数操作。

     /**
         * Initializes a Thread.
         * 初始化线程对象,里面各种初始化操作
         *
         * @param g                   the Thread group 线程组
         * @param target              the object whose run() method gets called 线程执行任务对象
         * @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. 线程所需栈内存大小,如果为0,则忽略这个参数
         * @param acc                 the AccessControlContext to inherit, or
         *                            AccessController.getContext() if null 访问控制上下文
         * @param inheritThreadLocals if {@code true}, inherit initial values for
         *                            inheritable thread-locals from the constructing thread 访问控制上下文开关
         */
        private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize, AccessControlContext acc,
                          boolean inheritThreadLocals) {
            //如果线程名称为null,抛出空指针异常,默认:Thread-0等
            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();
        }

线程的状态

在看启动线程之前,看一下Thread中封装的线程状态”:
通过volatile修饰threadStatus保存线程的状态,肯定会发生多线程修改状态。

     /* Java thread status for tools,
         * initialized to indicate thread 'not yet started'
         */

        private volatile int threadStatus = 0;

通过枚举State定义了线程的6种的状态:

    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.
             * <p>
             * 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;
        }

通过sun.misc.VM.toThreadState(threadStatus)获取线程的状态。

     /**
         * Returns the state of this thread.
         * This method is designed for use in monitoring of the system state,
         * not for synchronization control.
         *
         * @return this thread's state.
         * @since 1.5
         */
        public State getState() {
            // get current thread state
            return sun.misc.VM.toThreadState(threadStatus);
        }
        public static java.lang.Thread.State toThreadState(int var0) {
            //4  0000 0000 0000 0100
            if ((var0 & 4) != 0) {
                return java.lang.Thread.State.RUNNABLE;
                //1024   0000 0100 0000 0000
            } else if ((var0 & 1024) != 0) {
                return java.lang.Thread.State.BLOCKED;
                //16  0000 0000 0001 0000
            } else if ((var0 & 16) != 0) {
                return java.lang.Thread.State.WAITING;
                //32  0000 0000 0010 0000
            } else if ((var0 & 32) != 0) {
                return java.lang.Thread.State.TIMED_WAITING;
                //2  0000 0000 0000 0010
            } else if ((var0 & 2) != 0) {
                return java.lang.Thread.State.TERMINATED;
            } else {
                //1  0000 0000 0000 0001
                return (var0 & 1) == 0 ? java.lang.Thread.State.NEW : java.lang.Thread.State.RUNNABLE;
            }
        }

线程的启动

看一下start()方法;
作用就是启动一个新的线程,执行Runnable中的run()方法:

    /**
         * Causes this thread to begin execution; the Java Virtual Machine
         * calls the <code>run</code> method of this thread.
         * <p>
         * The result is that two threads are running concurrently: the
         * current thread (which returns from the call to the
         * <code>start</code> method) and the other thread (which executes its
         * <code>run</code> method).
         * <p>
         * It is never legal to start a thread more than once.
         * In particular, a thread may not be restarted once it has completed
         * execution.
         *
         * @throws IllegalThreadStateException if the thread was already
         *                                     started.
         * @see #run()
         * @see #stop()
         */
        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".
             * //只有新建的线程,才能调用start方法。
             */
            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 {
                //native方法
                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 */
                }
            }
        }

        private native void start0();

启动一个线程一定要调用该线程的start方法,否则,并不会创建出新的线程来。


来源:https://www.jianshu.com/p/347ea7f881f8

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 【JMM】Thread源码分析之创建和启动线程

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏