Класс Java Thread Java Doc и интерпретация исходного кода

Java
Класс Java Thread Java Doc и интерпретация исходного кода

написать впереди

Этот класс является очень важным классом. Многие ключевые исходные коды класса в среде параллелизма Java в той или иной степени используют некоторые методы класса Thread. Если вы не понимаете поведение этих методов, вы никогда не сможете полностью понять исходный код класса Thread. структура параллелизма. Итак, этот класс должен быть интерпретирован, что является основой.

Базовые знания

1. Тело документа Java

1.1 Связанный контент

Класс Thread — это класс реализации класса Runnable. У него также есть подкласс ForkJoinWorkerThread.

1.2 Обзор

Класс Thread представляет поток в программе, выполняющей задачи. JVM позволяет программам одновременно запускать несколько потоков для одновременного выполнения задач. Все потоки имеют приоритет. Потоки с более высоким приоритетом будут выполняться первыми. Все потоки также могут быть помечены как демонические, то есть потоки демона. Если поток A создает поток B, то поток B будет иметь тот же приоритет, что и поток A. Если поток A является демоном, то B также унаследует эту функцию.

Когда запускается JVM, обычно присутствует поток, не являющийся демоном (класс, вызывающий основной метод). JVM будет продолжать выполняться, если не будут выполнены следующие условия:

  • Система вызывает метод выхода для прямого выхода из JVM.
  • Все потоки, не являющиеся демонами, умерли, либо выполняясь нормально, либо вызывая исключение

Существует два способа создания потока.

  1. Создайте подкласс класса Thread. Этот подкласс должен переопределить метод run класса Thread. Возьмите каштан:
  class PrimeThread extends Thread {
       long minPrime;
       PrimeThread(long minPrime) {
           this.minPrime = minPrime;
       }

       public void run() {
           // compute primes larger than minPrime
            . . .
       }
   }

Следующий код создаст поток и запустит его.

PrimeThread p = new PrimeThread(143);
p.start();
  1. Другой способ создать поток — объявить класс, реализующий интерфейс Runnable. Этот класс реализации реализует метод запуска Runnable. Затем передайте этот класс реализации в качестве параметра конструктора в Thread, а затем в thread.start. код показывает, как показано ниже:
class PrimeRun implements Runnable {
  long minPrime;
  PrimeRun(long minPrime) {
     this.minPrime = minPrime;
  }

  public void run() {
     // compute primes larger than minPrime
     . . .
  }
}

Следующий код создаст поток и запустит его.

PrimeRun p = new PrimeRun(143);
new Thread(p).start();

Все потоки имеют имя для легкой идентификации. Несколько потоков могут иметь одно и то же имя. Если имя потока не указано, система сгенерирует его для вас при создании потока, например, поток-0. Кроме того, если вы передадите пустой Runnable конструктору потока, будет сообщено об NPE (исключение нулевого указателя).

Если интервьюер задаст вам вопрос во время интервью, сколько существует способов создания потоков в Java? Увидев здесь, вы должны знать, каков ответ.Если вы не посмотрите официальную документацию по Java, вы не сможете точно сказать, сколько существует способов. Конечно, вы можете зайти в Интернет, чтобы проверить сообщения, но никто не может гарантировать вам, что сообщения, написанные этими людьми в Интернете, должны быть правильными.Вы должны подумать сами, прежде чем дать положительный ответ, иначе есть возможность опрокидывания в любой момент.

1.3 Внутренние классы

1.3.1 Шесть состояний потоков Java Thread.State

Thread.State — это внутренний класс в Thread.Я написал статью о Thread.State и добавил несколько примеров кода, чтобы углубить понимание и память, пожалуйста.кликните сюда

1.3.2 Обработка исключений дочерних потоков Thread.UncaughtExceptionHandler

Thread.UncaughtExceptionHandler — это внутренний класс, на Thread.UncaughtExceptionHandler я также открыл отдельную статью, и с соответствующей сценой для демонстрации, заинтересованные могут прочитать, что работает код, улучшающий память, пожалуйстакликните сюда

1.4 общедоступные статические переменные

Эти три переменные описывают приоритет потока.

1.4.1 public static final int MIN_PRIORITY = 1

минимальный приоритет потока

1.4.2 public static final int NORM_PRIORITY = 5

приоритет потока по умолчанию

1.4.3 public static final int MAX_PRIORITY = 10

максимальный приоритет потока

1.5 Конструктор

1.5.1 public Thread()

Выделите новый поток. Этот конструктор является следствием Thread(null, null, gname), где gname — это имя вновь созданного потока. Правило генерации имени потока: "Thread-"+n, n - целое число.

1.5.2 public Thread(Runnable target)

target - передать задачу на выполнение.При вызове thread.start будет выполнен метод target.run.Если он пустой, то поток ничего не сделает.

1.5.3 public Thread(ThreadGroup group,Runnable target)

group - Вы можете указать группу потоков этого потока. Если группа потоков пуста, будет использоваться группа потоков текущего потока

1.5.4 public Thread(String name)

name - указывает имя потока

1.5.5 public Thread(ThreadGroup group,String name)

не так много, чтобы сказать

1.5.6 public Thread(Runnable target,String name)

не так много, чтобы сказать

1.5.7 public Thread(ThreadGroup group,Runnable target,String name)

не так много, чтобы сказать

1.5.8 public Thread(ThreadGroup group,Runnable target,String name,long stackSize)

Это нужно сказать Сосредоточьтесь на параметре stackSize. размер стека — это размер стека этого потока, который является приблизительным значением в байтах. Поведение этого параметра зависит главным образом от платформы, на которой работает jvm.

На некоторых платформах увеличение stackSize может позволить потокам достичь большей глубины рекурсии. Точно так же уменьшение stackSize может сэкономить место в памяти, так что количество одновременно работающих потоков будет выше. Отношение между параметром stackSize, глубиной рекурсии потока и числом параллелизма зависит в основном от того, как его реализует операционная система. На некоторых платформах установка stackSize может не работать.

JVM может использовать параметр stackSize в качестве предложения. Если вы установите очень маленькое значение, которое просто неразумно, JVM заменит это значение минимальным значением операционной системы по умолчанию.Наоборот, если вы установите очень большое значение (например, несколько терабайт), JVM заменит до максимального значения по умолчанию. Опять же, JVM может сделать некоторые компромиссы в отношении установленного вами значения, а затем скорректировать его вверх и вниз по мере необходимости (или полностью игнорировать значение).

Если указать значение 0 для параметра stackSize, это эквивалентно игнорированию этого значения, поэтому этот конструктор эквивалентен Thread(ThreadGroup, Runnable, String).

Если вы собираетесь изменить это значение, вам лучше сначала провести тест. Размер стека потоков для систем Windows и Linux может различаться.Если вы хотите настроить размер стека, убедитесь, что ваш тест охватывает все платформы, на которых может работать программа, иначе вы можете наступить на яму.

Parameters:
group - группа потоков
target - задача для выполнения
name - имя потока
stackSize - размер стека потока, в байтах. Если установлено значение 0, этот параметр игнорируется и используется значение по умолчанию.

1.6 Методы

1.6.1 public static Thread currentThread()

Возвращает ссылку на текущий исполняемый поток.

1.6.2 public static void yield()

Вызов этого метода сообщает планировщику потоков, что текущий поток может отказаться от использования ЦП. Планировщик также может игнорировать этот запрос. Целью разработки этого метода является попытка улучшить высокую загрузку ЦП некоторыми потоками во время многопоточного взаимодействия. Использование этого метода должно быть тщательно проверено, чтобы убедиться, что метод действительно работает так, как ожидалось.

Этот метод редко используется. Это может быть полезно во время отладки или тестирования, хотя, чтобы помочь воспроизводить ошибки.

1.6.3 public static void sleep(long millis)throws InterruptedException

Вызов этого метода приводит к тому, что текущий исполняемый поток приостанавливается на определенный период времени, фактическое время ожидания зависит от планировщика и системных таймеров. Поток по-прежнему будет удерживать блокировку, пока он спит.
Parameters:
миллис - время сна в миллисекундах
Throws:
IllegalArgumentException — генерирует это исключение, если аргумент миллисекунд передается как отрицательное число.
InterruptedException — если другие потоки вызывают метод прерывания этого потока, пока поток находится в спящем режиме, это исключение будет сгенерировано этим потоком, и поток может выполнить некоторую обработку в соответствии со своей собственной логикой.

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

Вызов этого метода приводит к тому, что текущий исполняемый поток приостанавливается на указанное количество миллисекунд + наносекунды, фактическое время ожидания зависит от планировщика и системных таймеров. Поток по-прежнему будет удерживать блокировку, пока он спит.
Parameters:
миллисекунды - количество миллисекунд, чтобы спать для
nanos - 0-999999 дополнительных наносекунд
Throws:
IllegalArgumentException - если аргумент миллисекунд отрицателен или наносекунды > 0 или InterruptedException — если другие потоки вызывают метод прерывания этого потока, пока поток находится в спящем режиме, это исключение будет сгенерировано этим потоком, и поток может выполнить некоторую обработку в соответствии со своей собственной логикой.

1.6.5 protected Object clone()throws CloneNotSupportedException

Нет смысла клонировать поток, он фактически запускает новый поток.Вы можете объявить пользовательский поток для наследования Thread и переопределить метод клонирования, и даже если вы это сделаете, он всегда будет вызывать CloneNotSupportedException, если вы вызываете этот метод. Так что этот метод можно игнорировать и даже не думать о нем.
Overrides:
методы, которые должны быть переопределены в подклассах
Returns:
Клон этого экземпляра всегда будет вызывать исключение и не будет возвращаться.
Throws:
CloneNotSupportedException - всегда выдавать это исключение

1.6.6 public void start()

Пусть поток начнет выполняться, и JVM вызовет метод запуска потока. Вызов этого метода приведет к одновременному выполнению двух потоков: один — текущий поток, а другой — поток, в котором вы объявили и вызвали start(). Поток не должен запускаться дважды, и если вы его вызовете, он не будет выполняться дважды, и будет выброшено исключение.

Throws:
IllegalThreadStateException — если поток уже запущен и вы снова вызываете start, будет выдано исключение.

1.6.7 public void run()

Если поток инициализируется конкретным объектом Runnable, то в конечном итоге будет выполнен метод run этого объекта. В противном случае этот метод ничего не делает. Подклассы Thread должны переопределять этот метод.

1.6.8 public void interrupt()

Прервите эту ветку. Если поток заблокирован методами wait(), join(), sleep(), то флаг прерывания потока будет сброшен и будет получено InterruptedException. Если поток заблокирован селектором, состояние прерывания будет установлено, когда он получит метод прерывания, и он немедленно вернется, возможно, с ненулевым значением, точно так же, как обычно возвращается метод select. Прерывание неактивного потока не имеет никакого эффекта.

1.6.9 public static boolean interrupted()

Проверьте, не был ли прерван текущий поток. Этот метод будет очищать состояние прерывания этого потока. То есть, если вы вызовете этот метод дважды, он вернет false во второй раз, если поток не будет снова прерван до второго вызова прерывания.

Returns:
Возвращает true, если поток был прерван, иначе возвращает false
See Also:
isInterrupted()

1.6.10 public boolean isInterrupted()

Проверьте, не прерван ли этот поток. Состояние прерывания не имеет никакого эффекта после вызова этого метода.

Returns:
Возвращает true, если поток был прерван, иначе возвращает false
See Also:
isInterrupted()

1.6.11 public final boolean isAlive()

Проверьте, активен ли этот поток. Поток считается живым, если он был запущен и еще не умер.

Возвращает: Возвращает true, если жив. вернуть false, если мертв

1.6.12 public final void setPriority(int newPriority)

Измените приоритет этого потока.

Parameters:
newPriority - новый приоритет
Броски: IllegalArgumentException - если приоритет больше не находится в диапазоне [MIN_PRIORITY,MAX_PRIORITY]
SecurityException - если текущий поток не может изменить этот поток

1.6.13 public final int getPriority()

Возвращает приоритет потока

1.6.14 public final void setName(String name)

Измените название этой темы

1.6.15 public final String getName()

Получить имя этого потока

1.6.16 public final ThreadGroup getThreadGroup()

Получает группу потоков, к которой принадлежит этот поток. Если поток умер, то этот метод вернет null.

1.6.17 public static int activeCount()

Возвращает расчетное значение, представляющее количество всех активных потоков в текущей группе потоков и подгруппе потоков.просто оценка. Рекурсивно перебирать все группы потоков и подгруппы потоков, к которым принадлежит этот поток.
Это расчетное значение, поскольку количество активных потоков может динамически меняться.Этот метод в основном используется для мониторинга и отладки.

1.6.18 public static int enumerate(Thread[] tarray)

Копирует все активные потоки потока текущего потока и группы подпотоков в массив входных параметров. Этот метод фактически вызывает ThreadGroup.enumerate(Thread[]) текущего потока.

Как правило, вы должны вызвать метод activeCount для подсчета размера нужного вам массива.Если длина группы входных параметров относительно мала и существует много фактических потоков, избыточные потоки будут игнорироваться.

Этот метод в основном используется для мониторинга и отладки.

1.6.19 public final void join(long millis) throws InterruptedException

Количество миллисекунд ожидания входного параметра до того, как поток остановится, т. е. поток завершит выполнение, но ему придется подождать немного дольше. Если параметр передан 0, он будет ждать вечно.

1.6.20 public final void join(long millis,int nanos)throws InterruptedException

ждать дополнительных наносекунд

1.6.21 public final void join()throws InterruptedException

это присоединиться (0)

1.6.22 public static void dumpStack()

Вывести информацию о стеке текущего потока. Этот метод используется только для отладки

1.6.23 public final void setDaemon(boolean on)

Отмечает, является ли этот поток потоком демона или пользовательским потоком. Он завершается, когда в JVM есть только потоки демона.Этот метод должен использоваться до вызова метода thread.start..

1.6.24 public final boolean isDaemon()

Проверьте, является ли этот поток потоком демона

1.6.25 public final void checkAccess()

Определите, имеет ли текущий поток разрешение на изменение этого потока. Выдает исключение без разрешения

1.6.26 public ClassLoader getContextClassLoader()

Возвращает ClassLoader для этого потока.

1.6.27 public void setContextClassLoader(ClassLoader cl)

установить этот загрузчик классов

1.6.28 public static boolean holdsLock(Object obj)

Определяет, удерживает ли текущий поток блокировку определенного объекта.

1.6.29 public StackTraceElement[] getStackTrace()

Возвращает массив информации о стеке, представляющий этот дамп потока. Если этот метод вызывается до запуска потока, он был запущен, но фактически не запущен, а ЦП не запланирован, завершен, то будет возвращен массив длины 0. Если длина возвращаемого массива не равна 0, то первый элемент массива — это метод, который был выполнен потоком дальше всего, а последний элемент массива — это последний выполненный вызов метода.

1.6.30 public static Map<Thread,StackTraceElement[]> getAllStackTraces()

Возвращает карту всех активных потоков и соответствующих им StackTrace. Эта информация о стеке является моментальными снимками, что означает, что информация о стеке всегда меняется, и это информация только в определенный момент.

1.6.31 public long getId()

Возвращает идентификатор этого потока. Идентификатор — это положительное длинное число, которое автоматически генерируется при создании потока. Этот идентификатор уникален и не может быть изменен до тех пор, пока поток не умрет. Но когда поток умирает, идентификатор потока может использоваться другими потоками.

1.6.32 public Thread.State getState()

Возвращает статус этого потока. Этот метод обычно используется для мониторинга состояния системы, а не для синхронизации управления.

1.6.33 public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

Установите UncaughExceptionHandler по умолчанию. Помните об UncauthExceptionHandler, когда исключение возникает во время выполнения потока и не перехватывается, оно передает поток и объект исключения этому обработчику для некоторой последующей обработки. Если у этого потока нет другого обработчика, будет использоваться этот обработчик по умолчанию. Подробности смотрите в другом моем посте, указанном выше.

1.6.34 public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()

Возвращает этот defaultHandler или null, если значение по умолчанию отсутствует.

1.6.35 public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()

не так много, чтобы сказать

1.6.36 public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

не так много, чтобы сказать

2. Интерпретация исходного кода Thread

Для чтения я отправил исходный код класса резьбы в наггетты.кликните сюдаВы можете просмотреть исходный код, чтобы прочитать следующие комментарии на английском языке

package java.lang;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;

public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
    //线程名称,通过setName,init方法可以设置
    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;

    //线程要执行的任务
    private Runnable target;

    //这个线程的线程组
    private ThreadGroup group;

    //这个线程的classLoader
    private ClassLoader contextClassLoader;

    //Java的安全管理器 具体有什么用,我还不清楚,后续搞清楚了会更新
    private AccessControlContext inheritedAccessControlContext;

    //如果new 线程时没有指定名称,会通过这个变量和下个方法生产一个序号作为线程name
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

    //这个线程的ThreadLocal对象,有关ThreadLocal我们单开帖子去讲
    ThreadLocal.ThreadLocalMap threadLocals = null;

    //这个具体什么作用不清楚
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    //线程栈大小
    private long stackSize;

    //这个字段源码没有用到,具体有什么作用不清楚,应该是JVM对线程的操作
    private long nativeParkEventPointer;

    //线程id
    private long tid;

    //为了生成有序的线程ID
    private static long threadSeqNumber;

    //线程的状态
    private volatile int threadStatus = 0;

    //为了生成有序的线程ID
    private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }

    /**
     * 这个和Lock框架有关,后续lock框架搞完再补充
     * The argument supplied to the current call to
     * java.util.concurrent.locks.LockSupport.park.
     * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
     * Accessed using java.util.concurrent.locks.LockSupport.getBlocker
     */
    volatile Object parkBlocker;

    /* The object in which this thread is blocked in an interruptible I/O
     * operation, if any.  The blocker's interrupt method should be invoked
     * after setting this thread's interrupt status.
     */
    private volatile Interruptible blocker;
    private final Object blockerLock = new Object();

    /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
     */
    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;

    /**
     * native方法,返回当前线程的引用
     * 什么是native方法,native方法就是jdk里面一些使用C++或C实现的较底层的方法
     */
    public static native Thread currentThread();

    /**
     * native方法,表示当前线程放弃CPU资源,暂停执行
     */
    public static native void yield();

    /**
     * native方法,sleep一会儿
     */
    public static native void sleep(long millis) throws InterruptedException;

    /**
     * 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);
    }

    /**
     * 初始化线程,其实就是调用最全的那个init
     */
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }

    /**
     * 初始化一个线程
     *
     * @param 线程组
     * @param 执行任务
     * @param 线程名称
     * @param 线程栈大小
     * @param 安全控制器
     * @param 继承的ThreadLocal,这个参数具体作用还需要再看一下
     */
    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) {
            //检查SecurityManager是否为空,如果不为空,使用SecurityManager的线程组
            if (security != null) {
                g = security.getThreadGroup();
            }

            //如果没有SecurityManager,就是用父线程的线程组
            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();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        //设置线程栈
        this.stackSize = stackSize;

        //调用静态私有方法生成一个线程ID
        tid = nextThreadID();
    }

    /**
     * 看代码,永远都会抛出一个CloneNotSupportedException异常,Thread类不支持克隆
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    /**
     * 无参的构造方法,不多说了,上面已经很详细了
     * 线程名使用nextThreadNum来设置
     */
    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);
    }

    /**
     * 启动线程,这个方法是个同步的方法
     */
    public synchronized void start() {
        /**
         * 如果不是刚new出来的线程,抛异常
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        // 线程组添加此线程,然后unStarted可以减少,具体看ThreadGroup源码
        group.add(this);
        
        boolean started = false;
        try {
            //调用原生方法启动线程
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                //啥也不干
            }
        }
    }
    //native方法,这个方法才是真正启动线程的方法
    private native void start0();

    /**
     * 不多说,这个是实现Runnable接口的方法
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    /**
     * 这个方法是JVM调用的,用来做一些清理工作
     */
    private void exit() {
        if (group != null) {
            group.threadTerminated(this);
            group = null;
        }
        //全都给置空
        target = null;
        threadLocals = null;
        inheritableThreadLocals = null;
        inheritedAccessControlContext = null;
        blocker = null;
        uncaughtExceptionHandler = null;
    }

    /**
     * 这个方法过时了,最好不要用,本文也不会去分析
     */
    @Deprecated
    public final void stop() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            checkAccess();
            if (this != Thread.currentThread()) {
                security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
            }
        }
        // A zero status value corresponds to "NEW", it can't change to
        // not-NEW because we hold the lock.
        if (threadStatus != 0) {
            resume(); // Wake up thread if it was suspended; no-op otherwise
        }

        // The VM can handle all thread states
        stop0(new ThreadDeath());
    }

    /**
     * 一样不要用
     */
    @Deprecated
    public final synchronized void stop(Throwable obj) {
        throw new UnsupportedOperationException();
    }

    /**
     * 打断线程
     */
    public void interrupt() {
        //判断权限
        if (this != Thread.currentThread())
            checkAccess();
        //这个锁还不太清楚,要去研究一下Lock
        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                //native方法
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        //native方法
        interrupt0();
    }

    /**
     * 静态方法,判断当前线程是否被打断,清除状态
     */
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

    /**
     * 判断是否打断,不清除状态
     */
    public boolean isInterrupted() {
        return isInterrupted(false);
    }

    /**
     * native方法,判断线程是否被打断了。
     * 这个线程的interrupted 状态是否会被重置主要取决于这个参数
     */
    private native boolean isInterrupted(boolean ClearInterrupted);

    /**
     * 不要用这个方法,已经过时了
     */
    @Deprecated
    public void destroy() {
        throw new NoSuchMethodError();
    }

    /**
     * native方法,判断这个线程是否还活着
     */
    public final native boolean isAlive();

    /**
     * 过时了,不要用
     */
    @Deprecated
    public final void suspend() {
        checkAccess();
        suspend0();
    }

    /**
     * 过时了,不要用
     */
    @Deprecated
    public final void resume() {
        checkAccess();
        resume0();
    }

    /**
     * 设置优先级
     */
    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();
            }
            //这也是native方法
            setPriority0(priority = newPriority);
        }
    }

    /**
     * 获取优先级
     */
    public final int getPriority() {
        return priority;
    }

    /**
     * 设置线程的名称
     */
    public final synchronized void setName(String name) {
        checkAccess();
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;
        if (threadStatus != 0) {
            //这是个native方法
            setNativeName(name);
        }
    }

    /**
     * 返回线程名
     */
    public final String getName() {
        return name;
    }

    /**
     * 获取这个线程的线程组
     */
    public final ThreadGroup getThreadGroup() {
        return group;
    }

    /**
     * 获取当前线程所在线程组的活跃线程数,这个值是动态的
     */
    public static int activeCount() {
        return currentThread().getThreadGroup().activeCount();
    }

    /**
     * 不多说了,详细的说明单开ThreadGroup去讲
     */
    public static int enumerate(Thread tarray[]) {
        return currentThread().getThreadGroup().enumerate(tarray);
    }

    /**
     * 过期了,不要用
     */
    @Deprecated
    public native int countStackFrames();

    /**
     * 线程任务执行完之后等待一段时间,核心方法是native的wait
     */
    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()) {
                //native方法,传0就是永远等下去
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                //等一会儿
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

    /**
     * 理论上是毫秒+指定的纳秒数,但是好像是骗人的
     */
    public final synchronized void join(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");
        }
        //这里纳秒大于500000等于是+了一毫秒,否则按照毫秒去Wait
        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }

    /**
     * 永远的join下去
     */
    public final void join() throws InterruptedException {
        join(0);
    }

    /**
     * 打印堆栈,只有debugg的时候使用,平时别用
     */
    public static void dumpStack() {
        new Exception("Stack trace").printStackTrace();
    }

    /**
     * 设置守护线程标志,记得是启动前设置
     */
    public final void setDaemon(boolean on) {
        checkAccess();
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on;
    }

    /**
     * 判断线程是否是守护线程
     */
    public final boolean isDaemon() {
        return daemon;
    }

    /**
     * 检查权限,后面会单开一个安全管理器的帖子去讲,日常很少用到
     */
    public final void checkAccess() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkAccess(this);
        }
    }

    /**
     * 打印线程的字符串表示
     */
    public String toString() {
        ThreadGroup group = getThreadGroup();
        if (group != null) {
            return "Thread[" + getName() + "," + getPriority() + "," +
                           group.getName() + "]";
        } else {
            return "Thread[" + getName() + "," + getPriority() + "," +
                            "" + "]";
        }
    }

    /**
     * 获取ClassLoader,注意CallerSensitive这个注解,调用者必须有权限
     * 涉及到ClassLoader的一些知识,后续单开帖子去讲
     */
    @CallerSensitive
    public ClassLoader getContextClassLoader() {
        if (contextClassLoader == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(contextClassLoader,
                                                   Reflection.getCallerClass());
        }
        return contextClassLoader;
    }

    /**
     * 设置这个ClassLoader
     */
    public void setContextClassLoader(ClassLoader cl) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("setContextClassLoader"));
        }
        contextClassLoader = cl;
    }

    /**
     * native方法,判断是否有锁
     */
    public static native boolean holdsLock(Object obj);
    
    //栈帧数组
    private static final StackTraceElement[] EMPTY_STACK_TRACE
        = new StackTraceElement[0];

    /**
     * 获取线程栈帧
     */
    public StackTraceElement[] getStackTrace() {
        if (this != Thread.currentThread()) {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkPermission(
                    SecurityConstants.GET_STACK_TRACE_PERMISSION);
            }
            
            if (!isAlive()) {
                return EMPTY_STACK_TRACE;
            }
            //dumpThreads这又是个native方法,其实是它来导出线程栈的
            StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
            StackTraceElement[] stackTrace = stackTraceArray[0];
            // 上面调用isAlive虽然返回true,但是可能后面线程死掉了,就会导致
            //stackTrace为null
            if (stackTrace == null) {
                stackTrace = EMPTY_STACK_TRACE;
            }
            return stackTrace;
        } else {
            // Don't need JVM help for current thread
            return (new Exception()).getStackTrace();
        }
    }

    /**
     * 获取所有线程的ThreadDump
     */
    public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkPermission(
                SecurityConstants.GET_STACK_TRACE_PERMISSION);
            security.checkPermission(
                SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
        }

        // native方法,获取所有活跃线程
        Thread[] threads = getThreads();
        StackTraceElement[][] traces = dumpThreads(threads);
        Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
        for (int i = 0; i < threads.length; i++) {
            StackTraceElement[] stackTrace = traces[i];
            if (stackTrace != null) {
                m.put(threads[i], stackTrace);
            }
        }
        return m;
    }


    private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
                    new RuntimePermission("enableContextClassLoaderOverride");

    /** cache of subclass security audit results */
    /* Replace with ConcurrentReferenceHashMap when/if it appears in a future
     * release */
    private static class Caches {
        /** cache of subclass security audit results */
        static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
            new ConcurrentHashMap<>();

        /** queue for WeakReferences to audited subclasses */
        static final ReferenceQueue<Class<?>> subclassAuditsQueue =
            new ReferenceQueue<>();
    }

    /**
     * Verifies that this (possibly subclass) instance can be constructed
     * without violating security constraints: the subclass must not override
     * security-sensitive non-final methods, or else the
     * "enableContextClassLoaderOverride" RuntimePermission is checked.
     */
    private static boolean isCCLOverridden(Class<?> cl) {
        if (cl == Thread.class)
            return false;

        processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
        WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
        Boolean result = Caches.subclassAudits.get(key);
        if (result == null) {
            result = Boolean.valueOf(auditSubclass(cl));
            Caches.subclassAudits.putIfAbsent(key, result);
        }

        return result.booleanValue();
    }

    /**
     * Performs reflective checks on given subclass to verify that it doesn't
     * override security-sensitive non-final methods.  Returns true if the
     * subclass overrides any of the methods, false otherwise.
     */
    private static boolean auditSubclass(final Class<?> subcl) {
        Boolean result = AccessController.doPrivileged(
            new PrivilegedAction<Boolean>() {
                public Boolean run() {
                    for (Class<?> cl = subcl;
                         cl != Thread.class;
                         cl = cl.getSuperclass())
                    {
                        try {
                            cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
                            return Boolean.TRUE;
                        } catch (NoSuchMethodException ex) {
                        }
                        try {
                            Class<?>[] params = {ClassLoader.class};
                            cl.getDeclaredMethod("setContextClassLoader", params);
                            return Boolean.TRUE;
                        } catch (NoSuchMethodException ex) {
                        }
                    }
                    return Boolean.FALSE;
                }
            }
        );
        return result.booleanValue();
    }

    private native static StackTraceElement[][] dumpThreads(Thread[] threads);
    private native static Thread[] getThreads();

    //获取id
    public long getId() {
        return tid;
    }

    /**
     * 内部类,线程状态
     * 详细说明可以看我单开的帖子
     */
    public enum State {
        
        NEW,

        
        RUNNABLE,

        
        BLOCKED,

        
        WAITING,

        
        TIMED_WAITING,

        
        TERMINATED;
    }

    /**
     * 获取线程状态
     */
    public State getState() {
        // get current thread state
        return sun.misc.VM.toThreadState(threadStatus);
    }

    /**
     * 线程异常处理器
     */
    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        /**
         * 线程执行任务过程中出现未检查异常时,JVM会调用这个方法
         */
        void uncaughtException(Thread t, Throwable e);
    }

    //处理器
    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;

    //默认的处理器
    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    /**
     * 设置默认的处理器
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(
                new RuntimePermission("setDefaultUncaughtExceptionHandler")
                    );
        }

         defaultUncaughtExceptionHandler = eh;
     }

    /**
     * 获取默认的处理器
     */
    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
        return defaultUncaughtExceptionHandler;
    }

    /**
     * 如果处理器为空,就是用线程组作为处理器,因为线程组实现了这个接口
     */
    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

    /**
     * 设置线程处理器
     */
    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        checkAccess();
        uncaughtExceptionHandler = eh;
    }

    /**
     * 将异常转发给处理器,这个方法只会被JVM调用
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

    /**
     * 清理引用队列,关于引用,单开帖子去讲
     */
    static void processQueue(ReferenceQueue<Class<?>> queue,
                             ConcurrentMap<? extends
                             WeakReference<Class<?>>, ?> map)
    {
        Reference<? extends Class<?>> ref;
        while((ref = queue.poll()) != null) {
            map.remove(ref);
        }
    }

    /**
     *  关于引用,单开帖子去讲
     **/
    static class WeakClassKey extends WeakReference<Class<?>> {
        /**
         * saved value of the referent's identity hash code, to maintain
         * a consistent hash code after the referent has been cleared
         */
        private final int hash;

        /**
         * Create a new WeakClassKey to the given object, registered
         * with a queue.
         */
        WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
            super(cl, refQueue);
            hash = System.identityHashCode(cl);
        }

        /**
         * Returns the identity hash code of the original referent.
         */
        @Override
        public int hashCode() {
            return hash;
        }

        /**
         * Returns true if the given object is this identical
         * WeakClassKey instance, or, if this object's referent has not
         * been cleared, if the given object is another WeakClassKey
         * instance with the identical non-null referent as this one.
         */
        @Override
        public boolean equals(Object obj) {
            if (obj == this)
                return true;

            if (obj instanceof WeakClassKey) {
                Object referent = get();
                return (referent != null) &&
                       (referent == ((WeakClassKey) obj).get());
            } else {
                return false;
            }
        }
    }


    // The following three initially uninitialized fields are exclusively
    // managed by class java.util.concurrent.ThreadLocalRandom. These
    // fields are used to build the high-performance PRNGs in the
    // concurrent code, and we can not risk accidental false sharing.
    // Hence, the fields are isolated with @Contended.

    /** The current seed for a ThreadLocalRandom */
    @sun.misc.Contended("tlr")
    long threadLocalRandomSeed;

    /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
    @sun.misc.Contended("tlr")
    int threadLocalRandomProbe;

    /** Secondary seed isolated from public ThreadLocalRandom sequence */
    @sun.misc.Contended("tlr")
    int threadLocalRandomSecondarySeed;

    //以下全是原生方法
    private native void setPriority0(int newPriority);
    private native void stop0(Object o);
    private native void suspend0();
    private native void resume0();
    private native void interrupt0();
    private native void setNativeName(String name);
}

Прочитав исходный код класса Thread, понять это несложно, ведь многие основные операции реализованы с использованием нативных методов, но имейте в виду, что эти методы являются основой фундамента!