• Java中Thread源码剖析



                                           本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


    关于线程,用很长时间了,主线程下的子线程去做一些事情,就是一个代理模式,主线程分代理权给子线程,子线程帮主线程完成一些任务。

    线程的方法大部分都是使用Native使用,不允许应用层修改,是CPU调度的最基本单元。实现线程的方式有三种:使用内核线程、用户线程和混合线程来实现,奉行先行发生的原则。

    内核线程:每个生成的线程,都1:1配比一个内核线程来支持,即双线程机制,消耗一个内核资源,类似手机中应用进程

    用户线程:普通线程,高速且低耗,创建、切换、调度等问题都需要自己处理

    混合实现:降低被阻塞的风险,用户线程与内核线程相当于M:N的关系

    线程的调度方式主要有两种:协同式和抢占式,前者简单但不可控制,一个线程执行完通知另外一个;抢占式可以通过yield方法让出执行时间,Java目前就采用这种,同时可以使用设置优先级的方式来提前线程执行顺序,但有可能被“系统”关闭。


    今天我们来看下线程的源码,进行系统的学习。

    1、首先线程有六种状态

        public enum State {
            /**
             * The thread has been created, but has never been started.
             */
            NEW,
            /**
             * The thread may be run.
             */
            RUNNABLE,
            /**
             * The thread is blocked and waiting for a lock.
             */
            BLOCKED,
            /**
             * The thread is waiting.
             */
            WAITING,
            /**
             * The thread is waiting for a specified amount of time.
             */
            TIMED_WAITING,
            /**
             * The thread has been terminated.
             */
            TERMINATED
        }

    NEW:刚创建还没启动

    RUNNABLE:可以执行 

    BLOCKED:堵塞状态,等待持有锁

    WAITING :处理等待状态 

    TIMED_WAITING:等待一些时间

    TERMINATED:终止

        /**
         * The maximum priority value allowed for a thread.
         */
        public static final int MAX_PRIORITY = 10;


        /**
         * The minimum priority value allowed for a thread.
         */
        public static final int MIN_PRIORITY = 1;


        /**
         * The normal (default) priority value assigned to threads.
         */
        public static final int NORM_PRIORITY = 5;

    2、分别是线程可设置的最大、最小和默认优先级,级别越高执行越靠前

        /**
         * Holds the thread's ID. We simply count upwards, so
         * each Thread has a unique ID.
         */
        private long id;

    3、每个线程都有一个独一无二的ID

    public Thread() {
            create(null, null, null, 0);
        }

     private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
            Thread currentThread = Thread.currentThread();
            if (group == null) {
                group = currentThread.getThreadGroup();
            }


            if (group.isDestroyed()) {
                throw new IllegalThreadStateException("Group already destroyed");
            }


            this.group = group;


            synchronized (Thread.class) {
                id = ++Thread.count;
            }


            if (threadName == null) {
                this.name = "Thread-" + id;
            } else {
                this.name = threadName;
            }


            this.target = runnable;
            this.stackSize = stackSize;


            this.priority = currentThread.getPriority();


            this.contextClassLoader = currentThread.contextClassLoader;


            // Transfer over InheritableThreadLocals.
            if (currentThread.inheritableValues != null) {
                inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
            }
            // add ourselves to our ThreadGroup of choice
            this.group.addThread(this);
        }

    4、初始化一个空的线程,获得当前运行的线程群组,设置id,name,执行线程runnable,池大小stackSize,优先级,并加入到线程群组,这是一个无参的Thread,正常情况下应该有ThreadGroup、Runnable、threadName和stackSize这四个参数。一般threadName如果为空,则报出NullPointerException,stackSize默认为0。

        /**
         * Destroys the receiver without any monitor cleanup.
         *
         * @deprecated Not implemented.
         */
        @Deprecated
        public void destroy() {
            throw new NoSuchMethodError("Thread.destroy()"); // TODO Externalize???
        }

    5、destroy方法在java7已经被抛弃。

        public void interrupt() {
            synchronized (interruptActions) {
                for (int i = interruptActions.size() - 1; i >= 0; i--) {
                    interruptActions.get(i).run();
                }
            }

            VMThread vmt = this.vmThread;
            if (vmt != null) {
                vmt.interrupt();
            }
        }

    6、停止当前线程,如果线程处于wait、join、sleep状态的线程,会报异常。

      public final boolean isAlive() {
            return (vmThread != null);
        }

    7、线程是否死掉,主要是判断虚拟机线程有没有死掉VMThread,当然获得当前线程也是通过VMThread.currentThread(),以及接下下获得当前线程处于六大状态中的哪种。

        public State getState() {
            // TODO This is ugly and should be implemented better.
            VMThread vmt = this.vmThread;


            // Make sure we have a valid reference to an object. If native code
            // deletes the reference we won't run into a null reference later.
            VMThread thread = vmThread;
            if (thread != null) {
                // If the Thread Object became invalid or was not yet started,
                // getStatus() will return -1.
                int state = thread.getStatus();
                if(state != -1) {
                    return VMThread.STATE_MAP[state];
                }
            }
            return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
        }

     public final void join() throws InterruptedException {
            VMThread t = vmThread;
            if (t == null) {
                return;
            }


            synchronized (t) {
                while (isAlive()) {
                    t.wait();
                }
            }
        }

    8、join堵塞当前线程,使其处于等待状态,因为子线程执行的时间可能比主线程执行时间还长,所以join是主线程需要在它执行完后再销毁。当然也可以加参数join(long millis, int nanos),使其等待N秒N毫秒,如果它已经处于join方法,则报InterruptedException 。

        public final void setDaemon(boolean isDaemon) {
            if (hasBeenStarted) {
                throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
            }


            if (vmThread == null) {
                daemon = isDaemon;
            }
        }

    9、设置为守护线程,必须的runnable执行前设置,会在其他已经没有非守护线程运行的时候执行。

        public final void setPriority(int priority) {
            if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
                throw new IllegalArgumentException("Priority out of range"); // TODO Externalize?
            }


            if (priority > group.getMaxPriority()) {
                priority = group.getMaxPriority();
            }


            this.priority = priority;


            VMThread vmt = this.vmThread;
            if (vmt != null) {
                vmt.setPriority(priority);
            }
        }

    10、优先级主要通过VMThread来设置的,注意最高设为10最低为1,否则报 IllegalArgumentException。

       public static void sleep(long millis, int nanos) throws InterruptedException {

            VMThread.sleep(millis, nanos);
        }

    11、执行sleep,如果在sleep期间被interrupt,会报InterruptedException。

        /**
         * Starts the new Thread of execution. The <code>run()</code> method of
         * the receiver will be called by the receiver Thread itself (and not the
         * Thread calling <code>start()</code>).
         *
         * @throws IllegalThreadStateException if the Thread has been started before
         *
         * @see Thread#run
         */
        public synchronized void start() {
            if (hasBeenStarted) {
                throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
            }


            hasBeenStarted = true;


            VMThread.create(this, stackSize);
        }

    12、线程开始执行,如果start已经执行,则报IllegalThreadStateException

        @Deprecated
        public final synchronized void stop(Throwable throwable) {
            throw new UnsupportedOperationException();
        }

    13、stop方法弃用

    public static void yield() {
            VMThread.yield();
        }

    14、给另一个准备运行的线程让路,让它先执行

    关于join和yield的区别,更在上一节: 

    Java中join和yield的作用



  • 相关阅读:
    向工信部投诉中国联通、移动、电信等运营服务商的权威途径
    如何把本机Sql Sever数据库转移到虚拟主机sql数据库
    SQL Server 2005如何远程连接数据库?
    mssql server 2005还原数据库bak文件与“备份集中的数据库备份与现有的xx数据库不同”解决方法
    傲游5里保存的网址,在傲游4不能同步?外加几句吐槽
    mysql数据库基础的简单操作指南
    MVC框架模式技术实例(用到隐藏帧、json、仿Ajax、Dom4j、jstl、el等)
    Web---JSTL(Java标准标签库)-Core核心标签库、I18N国际化、函数库
    Jupyter Notebook导入自定义模块时ImportError
    Pandas数据处理(2): 数据透视表,行转列、列转行、以及一行生成多行
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6147356.html
Copyright © 2020-2023  润新知