Thread源码解读

    今天,短暂的经历了人生的失意后,已经皮实了。我要将今年学的东西进行归纳总结。
    Thread类算是源码比较简单的类,现对其进行刨析。后续所有分享都是基于java1.8。

一、Thread类的私有参数

public
class Thread implements Runnable {
//Thread 类继承自Runnable接口,Runnable接口只有一个方法既run方法,所以实现线程的两种方法,继承Tread类和实现Runnable接口本质上都是基于Runnable来实现的,最终都是重写了Runnable接口中的run方法,参考java继承机制。
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
//这几个变量没有查到被使用过,先放在这,后续研究一下
    private volatile String name;
    private int            priority;
    private Thread         threadQ;//
    private long           eetop;
    private boolean     single_step;
    private boolean     daemon = false;
    private boolean     stillborn = false;
//构造函数中会传入的runnable实现的接受者
    private Runnable target;
 //线程组,一个线程必然有线程组
    private ThreadGroup group;
//线程加载器
    private ClassLoader contextClassLoader;
//???
    private AccessControlContext inheritedAccessControlContext;
//静态变量,使用内部静态类的单例模式,全局存在,用来生成线程名
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
//threadLocal,后面会单独研究这个类
    ThreadLocal.ThreadLocalMap threadLocals = null;
//提供父进程到子进程的threalocal里的局部变量
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
  //预期堆栈大小,不指定默认为0,0代表忽略这个属性。与平台相关,不建议使用该属性。
    private long stackSize;
 //JVM使用的变量
    private long nativeParkEventPointer;
   //线程ID
    private long tid;
//静态变量 ++新创建线程后自增
    private static long threadSeqNumber;
//JVM变量,线程状态,NEW,RUNNABLE,WAITING,BLOCKED,TIMED_WAITING,TIMED_WAITING
    private volatile int threadStatus = 0;
//返回线程ID
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }
//中断相关 LockSupport
    volatile Object parkBlocker;
//interrupt
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();
    void blockedOn(Interruptible b) {
        synchronized (blockerLock) {
            blocker = b;
        }
    }
//线程的优先级常量
    public final static int MIN_PRIORITY = 1;//最低级别
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;//最高级别

二、Thread 初始化分析

//本地yield方法
        public static native void yield();
//本地sleep方法
        public static native void sleep(long millis) throws     InterruptedException;    private void 
//初始化方法
        init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
        }
//初始化的完全方法
        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();//父线程是当前线程
      //初始化group,如果有安全线程,就获取安全线程的group,否则获取父线程的安全线程
        SecurityManager security = System.getSecurityManager();
        if (g == null) {//作为start方法的接收target
            //
            if (security != null) {
                g = security.getThreadGroup();
            }
            //
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }
       //
        g.checkAccess();
       //
        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();
       //将runnable赋值给Thread,设置优先级
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        //设置栈大小
        this.stackSize = stackSize;
        //设置线程ID
        tid = nextThreadID();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
//下面有这么些种类的Tread()初始化构造函数,
    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);
    }

三、Thread常用方法实现分析
1、start()方法

public synchronized void start() {
   //threadStatus初始化为0
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
//通知group添加这个线程
        group.add(this);
        boolean started = false;
        try {
            start0();
            started = true;//用来在start0异常退出时,从group线程组中移除该thread
        } 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 */
            }
        }
    }
//native方法
    private native void start0();
//group的方法,通过向线程池里添加线程,有线程池来管理线程
ThreadGroup::void add(Thread t) {
        synchronized (this) {
            if (destroyed) {
                throw new IllegalThreadStateException();
            }
            if (threads == null) {
                threads = new Thread[4];
            } else if (nthreads == threads.length) {
                threads = Arrays.copyOf(threads, nthreads * 2);
            }
            threads[nthreads] = t;

            // This is done last so it doesn't matter in case the
            // thread is killed
            nthreads++;

            // The thread is now a fully fledged member of the group, even
            // though it may, or may not, have been started yet. It will prevent
            // the group from being destroyed so the unstarted Threads count is
            // decremented.
            nUnstartedThreads--;
        }
    }
   //该Thread继承了Runnable,线程实现有两种方法,一种是继承Thread重写run方法,一种是实现Runnable然后通过构造函数赋值给target,如果是第一种相当于重写了下面这个run方法,如果是第二种相当于调用了Runnable实现的run方法
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

2、exit()方法

//将所有改线程申请的资源清理掉
private void exit() {
       if (group != null) {
           group.threadTerminated(this);
           group = null;
       }
       /* Aggressively null out all reference fields: see bug 4006245 */
       target = null;
       /* Speed the release of some of these resources */
       threadLocals = null;
       inheritableThreadLocals = null;
       inheritedAccessControlContext = null;
       blocker = null;
       uncaughtExceptionHandler = null;
   }

3、interrupt()方法

//中断方法
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();
    }

4、join方法

public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
//自旋等待
            while (isAlive()) {
                wait(0);
            }
        } else {
//超时自旋等待
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

5、sleep()方法

public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

6 、setPriority方法

public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容

  • 北京大学(中国)校训:“自由平等,民主科学。” 话说,所有不谈源码的开发讲解都是瞎扯淡。今天,阴雨绵绵,心中暑气全...
    阿伦故事2019阅读 526评论 0 1
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 2,952评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,444评论 1 15
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,369评论 0 4
  • Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来、以及如何在Java中怎么创建线程...
    哥哥是欧巴Vitory阅读 376评论 0 0