Thread 源码详解

本贴最后更新于 2536 天前,其中的信息可能已经时异事殊

package java.lang;

/**thread 是程序中的一个执行程序,java 虚拟机允许一个应用有多个线程同时运行

  • A thread is a thread of execution in a program. The Java

  • Virtual Machine allows an application to have multiple threads of

  • execution running concurrently.

每个线程都有优先级,更高优先级的线程比低优先级优先运行。

每个线程都有可能被标记为守护线程 daemon。当代码运行时,一些线程差 UN 构建一个新的 Thread 对象,新的 thread 优先级初始设置等于创建该线程的优先级,当且精当创建线程的线程是一个守护线程时候,才会创建一个守护线程(什么是守护线程:http://blog.csdn.net/shimiso/article/details/8964414

只要还有任何非守护线程在运行,那么这个 Java 程序也在继续运行。当该程序中所有的非守护线程都终止时,虚拟机实例将自动退出。

  • Every thread has a priority. Threads with higher priority are

  • executed in preference to threads with lower priority. Each thread

  • may or may not also be marked as a daemon. When code running in

  • some thread creates a new Thread object, the new

  • thread has its priority initially set equal to the priority of the

  • creating thread, and is a daemon thread if and only if the

  • creating thread is a daemon.

当 java 虚拟机启动的时候,有一个单非守护线程(通常被称作 main 方法)

java 虚拟机会一直运行这个线程知道下面一些情况发生:

1Runntime 方法的 exit 被调用并且安全管理通过了 exit 操作的发生

2 所有的非守护线程都死了,另外被调用的 fun 方法抛出了异常

  • When a Java Virtual Machine starts up, there is usually a single

  • non-daemon thread (which typically calls the method named

  • main of some designated class). The Java Virtual

  • Machine continues to execute threads until either of the following

  • occurs:

  • The exit method of class Runtime has been

*     called and the security manager has permitted the exit operation

*     to take place.

  • All threads that are not daemon threads have died, either by

*     returning from the call to the run method or by

*     throwing an exception that propagates beyond the run

*     method.

有两个新建执行线程的方法,第一个被申明为继承 Thread 方法,基类必须覆盖 Thread 的 run 方法,

那么基类的一个示例就能被分配和开始线程了,例如 extends Thraed

  • There are two ways to create a new thread of execution. One is to

  • declare a class to be a subclass of Thread. This

  • subclass should override the run method of class

  • Thread. An instance of the subclass can then be

  • allocated and started. For example, a thread that computes primes

  • larger than a stated value could be written as follows:

*     class PrimeThread extends Thread {

*         long minPrime;

*         PrimeThread(long minPrime) {

*             this.minPrime = minPrime;

*         }

*         public void run() {

*             // compute primes larger than minPrime

*              . . .

*         }

*     }

  • The following code would then create a thread and start it running:

*     PrimeThread p = new PrimeThread(143);

*     p.start();

另一个方法是新建一个线程实现 Runable 接口,类去实现 run 方法,这个类的实例能被分配,通过作为参数传递到 THread 里面,并启动线程。

  • The other way to create a thread is to declare a class that

  • implements the Runnable interface. That class then

  • implements the run method. An instance of the class can

  • then be allocated, passed as an argument when creating

  • Thread, and started. The same example in this other

  • style looks like the following:

*     class PrimeRun implements Runnable {

*         long minPrime;

*         PrimeRun(long minPrime) {

*             this.minPrime = minPrime;

*         }

*         public void run() {

*             // compute primes larger than minPrime

*              . . .

*         }

*     }

  • The following code would then create a thread and start it running:

*     PrimeRun p = new PrimeRun(143);

*     new Thread(p).start();

每一个线程都有一个名字为了标记,不止一个线程拥有相同的名字,如果名字没有被指定的时候差 UN 构建了一个线程,那么会默认给一个新的名字。

  • Every thread has a name for identification purposes. More than

  • one thread may have the same name. If a name is not specified when

  • a thread is created, a new name is generated for it.

  • Unless otherwise noted, passing a {@code null} argument to a constructor

  • or method in this class will cause a {@link NullPointerException} to be

  • thrown.

  • @author  unascribed

  • @see     Runnable

  • @see     Runtime#exit(int)

  • @see     #run()

  • @see     #stop()

  • @since   JDK1.0

*/

public

class Thread implements Runnable {

类加载的时候,调用本地的注册本地方静态方法, 这个方法是本地方法

    /* Make sure registerNatives is the first thing does. */

    private static native void registerNatives();

    static {

        registerNatives();

    }

    private volatile char  name[];

    private int            priority;//优先级

    private Thread         threadQ;

    private long           eetop;

    /* Whether or not to single_step this thread. */

    private boolean     single_step;

    是否是守护线程

    /* Whether or not the thread is a daemon thread. */

    private boolean     daemon = false;

    /* JVM state */

    private boolean     stillborn = false;

要执行的 run 方法的对象

    /* What will be run. */

    private Runnable target;

这个线程的线程组

    /* The group of this thread */

    private ThreadGroup group;

这个线程的上下文类加载器

    /* The context ClassLoader for this thread */

    private ClassLoader contextClassLoader;

此线程继承的 AccessCOntrollerContext

上下文环境,指的是:继承父类的一些属性,比如优先级,是否是守护线程

    /* The inherited AccessControlContext of this thread */

    private AccessControlContext inheritedAccessControlContext;

对没有命名的线程自动编号

    /* For autonumbering anonymous threads. */

    private static int threadInitNumber;

    private static synchronized int nextThreadNum() {

        return threadInitNumber++;

    }

    /* ThreadLocal values pertaining to this thread. This map is maintained

     * by the ThreadLocal class. */

    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*

     * InheritableThreadLocal values pertaining to this thread. This map is

     * maintained by the InheritableThreadLocal class.

     */

    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

    /*

    栈大小,默认是 0,具体分配由 jvm 决定

     * The requested stack size for this thread, or 0 if the creator did

     * not specify a stack size.  It is up to the VM to do whatever it

     * likes with this number; some VMs will ignore it.

     */

    private long stackSize;

    /*

    本地线程终止后任然存在的 JVM 私有状态

     * JVM-private state that persists after native thread termination.

     */

    private long nativeParkEventPointer;

    /*

    线程 ID

     * Thread ID

     */

    private long tid;

    产生 ThreadID 

    /* For generating thread ID */

    private static long threadSeqNumber;

    /* Java thread status for tools,

     * initialized to indicate thread 'not yet started'

     */

    private volatile int threadStatus = 0;

    private static synchronized long nextThreadID() {

        return ++threadSeqNumber;

    }

    /**

     * 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;

        }

    }

    /**

     * The minimum priority that a thread can have.

     */

    public final static int MIN_PRIORITY = 1;

   /**

     * The default priority that is assigned to a thread.

     */

    public final static int NORM_PRIORITY = 5;

    /**

     * The maximum priority that a thread can have.

     */

    public final static int MAX_PRIORITY = 10;

    /**

     * Returns a reference to the currently executing thread object.

     *返回一个实现当前在执行的线程

     * @return  the currently executing thread.

     */

    public static native Thread currentThread();

    /**

    提示当前调度器愿意去 yield 目前使用的处理器。调度程序可以自由忽视这个提示

     * A hint to the scheduler that the current thread is willing to yield

     * its current use of a processor. The scheduler is free to ignore this

     * hint.

  •      yield 是试图去改善相对的尝试去过度使用 cpu,它的使用应该与详细的分析和肌醇结合起来,确保它实际上具有积极的效果

     * Yield is a heuristic attempt to improve relative progression

     * between threads that would otherwise over-utilise a CPU. Its use

     * should be combined with detailed profiling and benchmarking to

     * ensure that it actually has the desired effect.

    这个方法的使用场景很少,最可能去用于调试和测试目的,这个可以帮助去重现 bug 由于竞争资源,他也可以当设计并发结构的时候

     * It is rarely 难的 appropriate 合适的 to use this method. It may be useful

     * for debugging or testing purposes, where it may help to reproduce

     * bugs due to race conditions. It may also be useful when designing

     * concurrency control constructs such as the ones in the

     * {@link java.util.concurrent.locks} package.

     */

    public static native void yield();

    /**

    让当前的在运行的线程 sleep(暂定停止执行) 一定的时间(毫秒),以系统的当前为准,线程不会丢失任何监控的所有权

     * Causes the currently executing thread to sleep (temporarily cease

     * execution) for the specified number of milliseconds, subject to

     * the precision and accuracy of system timers and schedulers. The thread

     * does not lose ownership of any monitors.

     *

     * @param  millis

     *         the length of time to sleep in milliseconds

     *

     * @throws  IllegalArgumentException

     *          if the value of {@code millis} is negative

     *

     * @throws  InterruptedException

     *          if any thread has interrupted the current thread. The

     *          interrupted status of the current thread is

     *          cleared when this exception is thrown.

     */

    public static native void sleep(long millis) throws InterruptedException;

    /**

    导致当前正在执行的线程休眠,毫秒加上指定的纳秒数

     * Causes the currently executing thread to sleep (temporarily cease

     * execution) for the specified number of milliseconds plus the specified

     * number of nanoseconds, subject to the precision and accuracy of system

     * timers and schedulers. The thread does not lose ownership of any

     * monitors.

     *

     * @param  millis

     *         the length of time to sleep in milliseconds

     *

     * @param  nanos

     *         {@code 0-999999} additional nanoseconds to sleep

     *

     * @throws  IllegalArgumentException

     *          if the value of {@code millis} is negative, or the value of

     *          {@code nanos} is not in the range {@code 0-999999}

     *

     * @throws  InterruptedException

     *          if any thread has interrupted the current thread. The

     *          interrupted status of the current thread is

     *          cleared when this exception is thrown.

     */

    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);

    }

    /**

    初始化一个线程带有当前上下文

    

     * Initializes a Thread with the current AccessControlContext.

     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext)

     */

    private void init(ThreadGroup g, Runnable target, String name,

                      long stackSize) {

        init(g, target, name, stackSize, null);

    }

    /**

     * Initializes a Thread.

     *初始化一个线程 初始化的基本方法

ThreadGroup g:ThreadGroup 线程组 线程组是一个可以统一管理的线程集合。默认情况下,即没有指定线程组的话,创建的所有线程属于相同的线程组。先将 secuity 的线程组赋给新线程的线程组,如果还是为空,则设为父线程的线程组。

     * @param g the Thread group

Runnable target:Runnable 对象,即装配线程要执行的 run()方法,this.target = target;

     * @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.

     * @param acc the AccessControlContext to inherit, or

     *            AccessController.getContext() if null

     */

    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();

    }

    /**

     抛出克隆不支持的异常并且新建一个新的线程来代替

     * Throws CloneNotSupportedException as a Thread can not be meaningfully

     * cloned. Construct a new Thread instead.

     *

     * @throws  CloneNotSupportedException

     *          always

     */

    @Override

    protected Object clone() throws CloneNotSupportedException {

        throw new CloneNotSupportedException();

    }

    /**

分配一个新的线程对象,这个构造函数

     * Allocates a new {@code Thread} object. This constructor has the same

     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}

     * {@code (null, null, gname)}, where {@code gname} is a newly generated

     * name. Automatically generated names are of the form

     * {@code "Thread-"+}n, where n is an integer.

     */

    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-"+}n, where n 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.

     */

    Thread(Runnable target, AccessControlContext acc) {

        init(null, target, "Thread-" + nextThreadNum(), 0, acc);

    }

    /**

     * Allocates a new {@code Thread} object. This constructor has the same

     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}

     * {@code (group, target, gname)} ,where {@code gname} is a newly generated

     * name. Automatically generated names are of the form

     * {@code "Thread-"+}n, where n is an integer.

     *

     * @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.

     *

     * @throws  SecurityException

     *          if the current thread cannot create a thread in the specified

     *          thread group

     */

    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}.

     *

     * If there is a security manager, its

     * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess}

     * method is invoked with the ThreadGroup as its argument.

     *

     * 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.

     *

     * 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.

     *

     * 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 stack size.

     *

     * 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.  The effect of the

     * {@code stackSize} parameter, if any, is highly platform dependent.

     *

     * 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 stackSize parameter

     * and the maximum recursion depth and concurrency level are

     * platform-dependent.  On some platforms, the value of the

     * {@code stackSize} parameter may have no effect whatsoever.

     *

     * 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).

     *

     * 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.

     *

     * 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.

     *

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

    }

    /**

    导致线程去开始执行,java 虚拟机调用这个线程的 run 方法

     * Causes this thread to begin execution; the Java Virtual Machine

     * calls the run method of this thread.

     *

    结果是两个线程同时运行,当前的线程(start 方法调用的的)和另一个(run 方法)

     * The result is that two threads are running concurrently: the

     * current thread (which returns from the call to the

     * start method) and the other thread (which executes its

     * run method).

     *

    

     * It is never legal to start a thread more than once.

     * In particular, a thread may not be restarted once it has completed

     * execution.

     *一个线程启动多次是不合法的,通常来说,一个线程不能被重启一旦他完成了执行

     * @exception  IllegalThreadStateException  if the thread was already

     *               started.

     * @see        #run()

     * @see        #stop()

     */

    public synchronized void start() {

        /**

    这个方法不是被 main 方法线程或者系统线程组通过 VM 创建,那就不会被 invoke。每一个新的线程组在未来都会被加入 vm 中,threadStatus 等于 0 表示还未执行的线程,新建的。

         * 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 */

            }

        }

    }

    private native void start0();

    /**

    如果构造函数被用于接受一个 Runable,那么这个方法会被调用,否则不会返回任何东西

     * If this thread was constructed using a separate

     * Runnable run object, then that

     * Runnable object's run method is called;

     * otherwise, this method does nothing and returns.

     *

     * Subclasses of Thread should override this method.

     *

     * @see     #start()

     * @see     #stop()

     * @see     #Thread(ThreadGroup, Runnable, String)

     */

    @Override

    public void run() {

        if (target != null) {

            target.run();

        }

    }

    /**

    这个方法被系统调用,并给这个线程机会去清理在正在退出户之前,所有参数都设置为 null

     * This method is called by the system to give a Thread

     * a chance to clean up before it actually exits.

     */

    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;

    }

    /**

    强制线程停止执行

     * Forces the thread to stop executing.

     *

    如果有安全管理被安装,则它的 checkAccess 调用方法 shis 调用,这可能会导致 SecurityException 被引发,在当前线程中。

     * If there is a security manager installed, its checkAccess

     * method is called with this

     * as its argument. This may result in a

     * SecurityException being raised (in the current thread).

     *

    如果这个线程和当前线程不一样(这个是,当前的线程尝试去停止除本身以外的线程)

    安全管理器的 checkPermission 方法被调动。另外这个可能被抛出 SecurityException 异常在当前线程中。

     * If this thread is different from the current thread (that is, the current

     * thread is trying to stop a thread other than itself), the

     * security manager's checkPermission method (with a

     * RuntimePermission("stopThread") argument) is called in

     * addition.

     * Again, this may result in throwing a

     * SecurityException (in the current thread).

     *

    这个线程相当于被这个线程强制停止,异常的和去新建一个 ThreadDeath 对象作为异常

    允许停止一个线程如果一个线程还没开始,如果线程已经启动了,他立即终止。

     * The thread represented by this thread is forced to stop whatever

     * it is doing abnormally and to throw a newly created

     * ThreadDeath object as an exception.

     *

     * It is permitted to stop a thread that has not yet been started.

     * If the thread is eventually started, it immediately terminates.

     *

    一个应用不应该去尝试捕获 ThreadDeath 除非他必须做一些额外的清理操作

     * An application should not normally try to catch

     * ThreadDeath unless it must do some extraordinary

     * cleanup operation (note that the throwing of

     * ThreadDeath causes finally clauses of

     * try statements to be executed before the thread

     * officially dies).  If a catch clause catches a

     * ThreadDeath object, it is important to rethrow the

     * object so that the thread actually dies.

     *

     * The top-level error handler that reacts to otherwise uncaught

     * exceptions does not print out a message or otherwise notify the

     * application if the uncaught exception is an instance of

     * ThreadDeath.

     *

     * @exception  SecurityException  if the current thread cannot

     *               modify this thread.

     * @see        #interrupt()

     * @see        #checkAccess()

     * @see        #run()

     * @see        #start()

     * @see        ThreadDeath

     * @see        ThreadGroup#uncaughtException(Thread,Throwable)

     * @see        SecurityManager#checkAccess(Thread)

     * @see        SecurityManager#checkPermission

    这个方法本质上是不安全的,停止线程的过程中会打开所有已经被锁的监视器。

     * @deprecated This method is inherently unsafe.  Stopping a thread with

     *       Thread.stop causes it to unlock all of the monitors that it

     *       has locked (as a natural consequence of the unchecked

     *       ThreadDeath exception propagating up the stack).  If

     *       any of the objects previously protected by these monitors were in

     *       an inconsistent state, the damaged objects become visible to

     *       other threads, potentially resulting in arbitrary behavior.  Many

     *       uses of stop should be replaced by code that simply

     *       modifies some variable to indicate that the target thread should

     *       stop running.  The target thread should check this variable

     *       regularly, and return from its run method in an orderly fashion

     *       if the variable indicates that it is to stop running.  If the

     *       target thread waits for long periods (on a condition variable,

     *       for example), the interrupt method should be used to

     *       interrupt the wait.

     *       For more information, see

     *       {@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why

     *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?.

     */

    @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());

    }

    /**

     * Throws {@code UnsupportedOperationException}.

     *

     * @param obj ignored

     *

     * @deprecated This method was originally designed to force a thread to stop

     *        and throw a given {@code Throwable} as an exception. It was

     *        inherently unsafe (see {@link #stop()} for details), and furthermore

     *        could be used to generate exceptions that the target thread was

     *        not prepared to handle.

     *        For more information, see

     *        {@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why

     *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?.

     */

    @Deprecated

    public final synchronized void stop(Throwable obj) {

        throw new UnsupportedOperationException();

    }

    /**中断这个线程

     * Interrupts this thread.

     *除非当前线程自己阻断了

     * Unless the current thread is interrupting itself, which is

     * always permitted, the {@link #checkAccess() checkAccess} method

     * of this thread is invoked, which may cause a {@link

     * SecurityException} to be thrown.

     *

     * If this thread is blocked in an invocation of the {@link

     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link

     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}

     * class, or of the {@link #join()}, {@link #join(long)}, {@link

     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},

     * methods of this class, then its interrupt status will be cleared and it

     * will receive an {@link InterruptedException}.

     *

     * If this thread is blocked in an I/O operation upon an {@link

     * java.nio.channels.InterruptibleChannel InterruptibleChannel}

     * then the channel will be closed, the thread's interrupt

     * status will be set, and the thread will receive a {@link

     * java.nio.channels.ClosedByInterruptException}.

     *

     * If this thread is blocked in a {@link java.nio.channels.Selector}

     * then the thread's interrupt status will be set and it will return

     * immediately from the selection operation, possibly with a non-zero

     * value, just as if the selector's {@link

     * java.nio.channels.Selector#wakeup wakeup} method were invoked.

     *

     * If none of the previous conditions hold then this thread's interrupt

     * status will be set.

     *

     * Interrupting a thread that is not alive need not have any effect.

     *

     * @throws  SecurityException

     *          if the current thread cannot modify this thread

     *

     * @revised 6.0

     * @spec JSR-51

     */

    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();

    }

    /**

    测试这个当前线程是否被阻塞了,阻塞状态

     * Tests whether the current thread has been interrupted.  The

     * interrupted status of the thread is cleared by this method.  In

     * other words, if this method were to be called twice in succession, the

     * second call would return false (unless the current thread were

     * interrupted again, after the first call had cleared its interrupted

     * status and before the second call had examined it).

     *

     * A thread interruption ignored because a thread was not alive

     * at the time of the interrupt will be reflected by this method

     * returning false.

     *

     * @return  true if the current thread has been interrupted;

     *          false otherwise.

     * @see #isInterrupted()

     * @revised 6.0

     */

    public static boolean interrupted() {

        return currentThread().isInterrupted(true);

    }

    /**

     * Tests whether this thread has been interrupted.  The interrupted

     * status of the thread is unaffected by this method.

     *

     * A thread interruption ignored because a thread was not alive

     * at the time of the interrupt will be reflected by this method

     * returning false.

     *

     * @return  true if this thread has been interrupted;

     *          false otherwise.

     * @see     #interrupted()

     * @revised 6.0

     */

    public boolean isInterrupted() {

        return isInterrupted(false);

    }

    /**

     * Tests if some Thread has been interrupted.  The interrupted state

     * is reset or not based on the value of ClearInterrupted that is

     * passed.

     */

    private native boolean isInterrupted(boolean ClearInterrupted);

    /**

     * Throws {@link NoSuchMethodError}.

     *这个方法本来是用于销毁一个线程而不做任何清理动作,每一个监视器都被帮助去被锁,他能产生思索,如果一个线程持有了一个保护关键系统资源的锁,被销毁了,但是没有释放资源,没有线程能再次拿到这个资源。如果另一个线程曾试图锁定这个资源会导致死锁,这种死锁表现通常会冻结自身,

     * @deprecated This method was originally designed to destroy this

     *     thread without any cleanup. Any monitors it held would have

     *     remained locked. However, the method was never implemented.

     *     If if were to be implemented, it would be deadlock-prone in

     *     much the manner of {@link #suspend}. If the target thread held

     *     a lock protecting a critical system resource when it was

     *     destroyed, no thread could ever access this resource again.

     *     If another thread ever attempted to lock this resource, deadlock

     *     would result. Such deadlocks typically manifest themselves as

     *     "frozen" processes. For more information, see

     *     {@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">

     *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.

     * @throws NoSuchMethodError always

     */

    @Deprecated

    public void destroy() {

        throw new NoSuchMethodError();

    }

    /**

     * Tests if this thread is alive. A thread is alive if it has

     * been started and has not yet died.

     *

     * @return  true if this thread is alive;

     *          false otherwise.

     */

    public final native boolean isAlive();

    /**

     暂停这个线程

     * Suspends this thread.

     *

     * First, the checkAccess method of this thread is called

     * with no arguments. This may result in throwing a

     * SecurityException (in the current thread).

     *

         如果这个线程在活动中,他被暂停并且不会再有进一步的进展,指导被恢复

     * If the thread is alive, it is suspended and makes no further

     * progress unless and until it is resumed.

     *

     * @exception  SecurityException  if the current thread cannot modify

     *               this thread.

     * @see #checkAccess

     会产生死锁问题

     * @deprecated   This method has been deprecated, as it is

     *   inherently deadlock-prone.  If the target thread holds a lock on the

     *   monitor protecting a critical system resource when it is suspended, no

     *   thread can access this resource until the target thread is resumed. If

     *   the thread that would resume the target thread attempts to lock this

     *   monitor prior to calling resume, deadlock results.  Such

     *   deadlocks typically manifest themselves as "frozen" processes.

     *   For more information, see

     *   {@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why

     *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?.

     */

    @Deprecated

    public final void suspend() {

        checkAccess();

        suspend0();

    }

    /**

     恢复一个被暂定的线程

     * Resumes a suspended thread.

     *

     * First, the checkAccess method of this thread is called

     * with no arguments. This may result in throwing a

     * SecurityException (in the current thread).

     *

     如果一个线程在活跃的时候被暂停了,被恢后他被允许继续在当前程序中执行。

     * If the thread is alive but suspended, it is resumed and is

     * permitted to make progress in its execution.

     *

     * @exception  SecurityException  if the current thread cannot modify this

     *               thread.

     * @see        #checkAccess

     * @see        #suspend()

     容易出现线程死锁

     * @deprecated This method exists solely for use with {@link #suspend},

     *     which has been deprecated because it is deadlock-prone.

     *     For more information, see

     *     {@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why

     *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?.

     */

    @Deprecated

    public final void resume() {

        checkAccess();

        resume0();

    }

    /**

     改变当前线程的优先级

     * Changes the priority of this thread.

     *

     * First the checkAccess method of this thread is called

     * with no arguments. This may result in throwing a

     * SecurityException.

     *

     否则,此线程的优先级设置为最小的值,制定的新优先级和最大的优先级

     * Otherwise, the priority of this thread is set to the smaller of

     * the specified newPriority and the maximum permitted

     * priority of the thread's thread group.

     *

     * @param newPriority priority to set this thread to

     * @exception  IllegalArgumentException  If the priority is not in the

     *               range MIN_PRIORITY to

     *               MAX_PRIORITY.

     * @exception  SecurityException  if the current thread cannot modify

     *               this thread.

     * @see        #getPriority

     * @see        #checkAccess()

     * @see        #getThreadGroup()

     * @see        #MAX_PRIORITY

     * @see        #MIN_PRIORITY

     * @see        ThreadGroup#getMaxPriority()

     */

    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);

        }

    }

    /**

     * Returns this thread's priority.

     *

     * @return  this thread's priority.

     * @see     #setPriority

     */

    public final int getPriority() {

        return priority;

    }

    /**

     给线程一个名字,必须在线程启动之前

     * Changes the name of this thread to be equal to the argument

     * name.

     *

     * First the checkAccess method of this thread is called

     * with no arguments. This may result in throwing a

     * SecurityException.

     *

     * @param      name   the new name for this thread.

     * @exception  SecurityException  if the current thread cannot modify this

     *               thread.

     * @see        #getName

     * @see        #checkAccess()

     */

    public final synchronized void setName(String name) {

        checkAccess();

        this.name = name.toCharArray();

        if (threadStatus != 0) {

            setNativeName(name);

        }

    }

    /**

     * Returns this thread's name.

     *

     * @return  this thread's name.

     * @see     #setName(String)

     */

    public final String getName() {

        return new String(name, true);

    }

    /**

     * Returns the thread group to which this thread belongs.

     * This method returns null if this thread has died

     * (been stopped).

     *

     * @return  this thread's thread group.

     */

    public final ThreadGroup getThreadGroup() {

        return group;

    }

    /**

     返回当前线程活动线程数的估计值,迭代递归当前所有子数组线程的线程组。

     * Returns an estimate of the number of active threads in the current

     * thread's {@linkplain java.lang.ThreadGroup thread group} and its

     * subgroups. Recursively iterates over all subgroups in the current

     * thread's thread group.

     *返回的值仅仅是一个估计值,因为线程的数值会动态变化当方法,可能会受某些系统线程的影响,

     此方法主要用于吊事和监控目的

     * The value returned is only an estimate because the number of

     * threads may change dynamically while this method traverses internal

     * data structures, and might be affected by the presence of certain

     * system threads. This method is intended primarily for debugging

     * and monitoring purposes.

     *

     * @return  an estimate of the number of active threads in the current

     *          thread's thread group and in any other thread group that

     *          has the current thread's thread group as an ancestor

     */

    public static int activeCount() {

        return currentThread().getThreadGroup().activeCount();

    }

    /**

     * Copies into the specified array every active thread in the current

     * thread's thread group and its subgroups. This method simply

     * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])}

     * method of the current thread's thread group.

     *

     * An application might use the {@linkplain #activeCount activeCount}

     * method to get an estimate of how big the array should be, however

     * if the array is too short to hold all the threads, the extra threads

     * are silently ignored.  If it is critical to obtain every active

     * thread in the current thread's thread group and its subgroups, the

     * invoker should verify that the returned int value is strictly less

     * than the length of {@code tarray}.

     *

     * Due to the inherent race condition in this method, it is recommended

     * that the method only be used for debugging and monitoring purposes.

     *

     * @param  tarray

     *         an array into which to put the list of threads

     *

     * @return  the number of threads put into the array

     *

     * @throws  SecurityException

     *          if {@link java.lang.ThreadGroup#checkAccess} determines that

     *          the current thread cannot access its thread group

     */

    public static int enumerate(Thread tarray[]) {

        return currentThread().getThreadGroup().enumerate(tarray);

    }

    /**

     * Counts the number of stack frames in this thread. The thread must

     * be suspended.

     *

     * @return     the number of stack frames in this thread.

     * @exception  IllegalThreadStateException  if this thread is not

     *             suspended.

     * @deprecated The definition of this call depends on {@link #suspend},

     *             which is deprecated.  Further, the results of this call

     *             were never well-defined.

     */

    @Deprecated

    public native int countStackFrames();

    /**

     等待时间这个线程结束,这个实现是一直循环看这个线程是否还存活,当线程结束的售后,其他线程被唤醒,被建议用 notifyall 代替,表示一个线程插入进来先运行

     * Waits at most {@code millis} milliseconds for this thread to

     * die. A timeout of {@code 0} means to wait forever.

     *

     * This implementation uses a loop of {@code this.wait} calls

     * conditioned on {@code this.isAlive}. As a thread terminates the

     * {@code this.notifyAll} method is invoked. It is recommended that

     * applications not use {@code wait}, {@code notify}, or

     * {@code notifyAll} on {@code Thread} instances.

     *

     * @param  millis

     *         the time to wait in milliseconds

     *

     * @throws  IllegalArgumentException

     *          if the value of {@code millis} is negative

     *

     * @throws  InterruptedException

     *          if any thread has interrupted the current thread. The

     *          interrupted status of the current thread is

     *          cleared when this exception is thrown.

     */

    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;

            }

        }

    }

    /**

     * Waits at most {@code millis} milliseconds plus

     * {@code nanos} nanoseconds for this thread to die.

     *

     * This implementation uses a loop of {@code this.wait} calls

     * conditioned on {@code this.isAlive}. As a thread terminates the

     * {@code this.notifyAll} method is invoked. It is recommended that

     * applications not use {@code wait}, {@code notify}, or

     * {@code notifyAll} on {@code Thread} instances.

     *

     * @param  millis

     *         the time to wait in milliseconds

     *

     * @param  nanos

     *         {@code 0-999999} additional nanoseconds to wait

     *

     * @throws  IllegalArgumentException

     *          if the value of {@code millis} is negative, or the value

     *          of {@code nanos} is not in the range {@code 0-999999}

     *

     * @throws  InterruptedException

     *          if any thread has interrupted the current thread. The

     *          interrupted status of the current thread is

     *          cleared when this exception is thrown.

     */

    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");

        }

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

            millis++;

        }

        join(millis);

    }

    /**

     * Waits for this thread to die.

     *

     * An invocation of this method behaves in exactly the same

     * way as the invocation

     *

     *

     * {@linkplain #join(long) join}{@code (0)}

     *

     *

     * @throws  InterruptedException

     *          if any thread has interrupted the current thread. The

     *          interrupted status of the current thread is

     *          cleared when this exception is thrown.

     */

    public final void join() throws InterruptedException {

        join(0);

    }

    /**

     * Prints a stack trace of the current thread to the standard error stream.

     * This method is used only for debugging.

     *

     * @see     Throwable#printStackTrace()

     */

    public static void dumpStack() {

        new Exception("Stack trace").printStackTrace();

    }

    /**

     * Marks this thread as either a {@linkplain #isDaemon daemon} thread

     * or a user thread. The Java Virtual Machine exits when the only

     * threads running are all daemon threads.

     *

     * This method must be invoked before the thread is started.

     *

     * @param  on

     *         if {@code true}, marks this thread as a daemon thread

     *

     * @throws  IllegalThreadStateException

     *          if this thread is {@linkplain #isAlive alive}

     *

     * @throws  SecurityException

     *          if {@link #checkAccess} determines that the current

     *          thread cannot modify this thread

     */

    public final void setDaemon(boolean on) {

        checkAccess();

        if (isAlive()) {

            throw new IllegalThreadStateException();

        }

        daemon = on;

    }

    /**

     * Tests if this thread is a daemon thread.

     *

     * @return  true if this thread is a daemon thread;

     *          false otherwise.

     * @see     #setDaemon(boolean)

     */

    public final boolean isDaemon() {

        return daemon;

    }

    /**

     确认当前当前在运行的线程时候有权限修改这个线程

     * Determines if the currently running thread has permission to

     * modify this thread.

     *

     

     * If there is a security manager, its checkAccess method

     * is called with this thread as its argument. This may result in

     * throwing a SecurityException.

     *

     * @exception  SecurityException  if the current thread is not allowed to

     *               access this thread.

     * @see        SecurityManager#checkAccess(Thread)

     */

    public final void checkAccess() {

        SecurityManager security = System.getSecurityManager();

        if (security != null) {

            security.checkAccess(this);

        }

    }

    /**

     * Returns a string representation of this thread, including the

     * thread's name, priority, and thread group.

     *

     * @return  a string representation of this thread.

     */

    public String toString() {

        ThreadGroup group = getThreadGroup();

        if (group != null) {

            return "Thread[" + getName() + "," + getPriority() + "," +

                           group.getName() + "]";

        } else {

            return "Thread[" + getName() + "," + getPriority() + "," +

                            "" + "]";

        }

    }

    /**

     返回一个上下文环境信息

     * Returns the context ClassLoader for this Thread. The context

     * ClassLoader is provided by the creator of the thread for use

     * by code running in this thread when loading classes and resources.

     * If not {@linkplain #setContextClassLoader set}, the default is the

     * ClassLoader context of the parent Thread. The context ClassLoader of the

     * primordial thread is typically set to the class loader used to load the

     * application.

     *

     * If a security manager is present, and the invoker's class loader is not

     * {@code null} and is not the same as or an ancestor of the context class

     * loader, then this method invokes the security manager's {@link

     * SecurityManager#checkPermission(java.security.Permission) checkPermission}

     * method with a {@link RuntimePermission RuntimePermission}{@code

     * ("getClassLoader")} permission to verify that retrieval of the context

     * class loader is permitted.

     *

     * @return  the context ClassLoader for this Thread, or {@code null}

     *          indicating the system class loader (or, failing that, the

     *          bootstrap class loader)

     *

     * @throws  SecurityException

     *          if the current thread cannot get the context ClassLoader

     *

     * @since 1.2

     */

    @CallerSensitive

    public ClassLoader getContextClassLoader() {

        if (contextClassLoader == null)

            return null;

        SecurityManager sm = System.getSecurityManager();

        if (sm != null) {

            ClassLoader.checkClassLoaderPermission(contextClassLoader,

                                                   Reflection.getCallerClass());

        }

        return contextClassLoader;

    }

    /**

     * Sets the context ClassLoader for this Thread. The context

     * ClassLoader can be set when a thread is created, and allows

     * the creator of the thread to provide the appropriate class loader,

     * through {@code getContextClassLoader}, to code running in the thread

     * when loading classes and resources.

     *

     * If a security manager is present, its {@link

     * SecurityManager#checkPermission(java.security.Permission) checkPermission}

     * method is invoked with a {@link RuntimePermission RuntimePermission}{@code

     * ("setContextClassLoader")} permission to see if setting the context

     * ClassLoader is permitted.

     *

     * @param  cl

     *         the context ClassLoader for this Thread, or null  indicating the

     *         system class loader (or, failing that, the bootstrap class loader)

     *

     * @throws  SecurityException

     *          if the current thread cannot set the context ClassLoader

     *

     * @since 1.2

     */

    public void setContextClassLoader(ClassLoader cl) {

        SecurityManager sm = System.getSecurityManager();

        if (sm != null) {

            sm.checkPermission(new RuntimePermission("setContextClassLoader"));

        }

        contextClassLoader = cl;

    }

    /**

     仅当当前线程持有锁的时候,返回 true

     这个方法设计师为了云溪一个程序去断定当前线程已经持有了一个特殊的锁

     * Returns true if and only if the current thread holds the

     * monitor lock on the specified object.

     *

     * This method is designed to allow a program to assert that

     * the current thread already holds a specified lock:

     *

     *     assert Thread.holdsLock(obj);

     *

     *

     * @param  obj the object on which to test lock ownership

     * @throws NullPointerException if obj is null

     * @return true if the current thread holds the monitor lock on

     *         the specified object.

     * @since 1.4

     */

    public static native boolean holdsLock(Object obj);

    private static final StackTraceElement[] EMPTY_STACK_TRACE

        = new StackTraceElement[0];

    /**

     返回堆栈元素代表栈堆数组的当前线程中,这个方法会返回长度为 0 的数组如果这个线程没有被启动,已经被启动但是被预定运行时间,或者已经终止。如果返回的数组长度不是 0 的话,那么数组的第一个元素表示堆栈的丁部,是最近使用的调用方法。数组的最后一个元素表示推展的底部。这是最近使用的调用

     * Returns an array of stack trace elements representing the stack dump

     * of this thread.  This method will return a zero-length array if

     * this thread has not started, has started but has not yet been

     * scheduled to run by the system, or has terminated.

     * If the returned array is of non-zero length then the first element of

     * the array represents the top of the stack, which is the most recent

     * method invocation in the sequence.  The last element of the array

     * represents the bottom of the stack, which is the least recent method

     * invocation in the sequence.

     *

     * If there is a security manager, and this thread is not

     * the current thread, then the security manager's

     * checkPermission method is called with a

     * RuntimePermission("getStackTrace") permission

     * to see if it's ok to get the stack trace.

     *

     * Some virtual machines may, under some circumstances, omit one

     * or more stack frames from the stack trace.  In the extreme case,

     * a virtual machine that has no stack trace information concerning

     * this thread is permitted to return a zero-length array from this

     * method.

     *

     * @return an array of StackTraceElement,

     * each represents one stack frame.

     *

     * @throws SecurityException

     *        if a security manager exists and its

     *        checkPermission method doesn't allow

     *        getting the stack trace of thread.

     * @see SecurityManager#checkPermission

     * @see RuntimePermission

     * @see Throwable#getStackTrace

     *

     * @since 1.5

     */

    public StackTraceElement[] getStackTrace() {

        if (this != Thread.currentThread()) {

            // check for getStackTrace permission

            SecurityManager security = System.getSecurityManager();

            if (security != null) {

                security.checkPermission(

                    SecurityConstants.GET_STACK_TRACE_PERMISSION);

            }

            // optimization so we do not call into the vm for threads that

            // have not yet started or have terminated

            if (!isAlive()) {

                return EMPTY_STACK_TRACE;

            }

            StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});

            StackTraceElement[] stackTrace = stackTraceArray[0];

            // a thread that was alive during the previous isAlive call may have

            // since terminated, therefore not having a stacktrace.

            if (stackTrace == null) {

                stackTrace = EMPTY_STACK_TRACE;

            }

            return stackTrace;

        } else {

            // Don't need JVM help for current thread

            return (new Exception()).getStackTrace();

        }

    }

    /**

     * Returns a map of stack traces for all live threads.

     * The map keys are threads and each map value is an array of

     * StackTraceElement that represents the stack dump

     * of the corresponding Thread.

     * The returned stack traces are in the format specified for

     * the {@link #getStackTrace getStackTrace} method.

     *

     * The threads may be executing while this method is called.

     * The stack trace of each thread only represents a snapshot and

     * each stack trace may be obtained at different time.  A zero-length

     * array will be returned in the map value if the virtual machine has

     * no stack trace information about a thread.

     *

     * If there is a security manager, then the security manager's

     * checkPermission method is called with a

     * RuntimePermission("getStackTrace") permission as well as

     * RuntimePermission("modifyThreadGroup") permission

     * to see if it is ok to get the stack trace of all threads.

     *

     * @return a Map from Thread to an array of

     * StackTraceElement that represents the stack trace of

     * the corresponding thread.

     *

     * @throws SecurityException

     *        if a security manager exists and its

     *        checkPermission method doesn't allow

     *        getting the stack trace of thread.

     * @see #getStackTrace

     * @see SecurityManager#checkPermission

     * @see RuntimePermission

     * @see Throwable#getStackTrace

     *

     * @since 1.5

     */

    public static Map, StackTraceElement[]> getAllStackTraces() {

        // check for getStackTrace permission

        SecurityManager security = System.getSecurityManager();

        if (security != null) {

            security.checkPermission(

                SecurityConstants.GET_STACK_TRACE_PERMISSION);

            security.checkPermission(

                SecurityConstants.MODIFY_THREADGROUP_PERMISSION);

        }

        // Get a snapshot of the list of all threads

        Thread[] threads = getThreads();

        StackTraceElement[][] traces = dumpThreads(threads);

        Map, 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);

            }

            // else terminated so we don't put it in the map

        }

        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,Boolean> subclassAudits =

            new ConcurrentHashMap<>();

        /** queue for WeakReferences to audited subclasses */

        static final ReferenceQueue> 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() {

                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();

    /**

     * Returns the identifier of this Thread.  The thread ID is a positive

     * long number generated when this thread was created.

     * The thread ID is unique and remains unchanged during its lifetime.

     * When a thread is terminated, this thread ID may be reused.

     *

     * @return this thread's ID.

     * @since 1.5

     */

    public long getId() {

        return tid;

    }

    /**

     * A thread state.  A thread can be in one of the following states:

     *

     * {@link #NEW}

     *     A thread that has not yet started is in this state.

     *    

     * {@link #RUNNABLE}

     *     A thread executing in the Java virtual machine is in this state.

     *    

     * {@link #BLOCKED}

     *     A thread that is blocked waiting for a monitor lock

     *     is in this state.

     *    

     * {@link #WAITING}

     *     A thread that is waiting indefinitely for another thread to

     *     perform a particular action is in this state.

     *    

     * {@link #TIMED_WAITING}

     *     A thread that is waiting for another thread to perform an action

     *     for up to a specified waiting time is in this state.

     *    

     * {@link #TERMINATED}

     *     A thread that has exited is in this state.

     *    

     *

     *

     *

     * A thread can be in only one state at a given point in time.

     * These states are virtual machine states which do not reflect

     * any operating system thread states.

     *

     * @since   1.5

     * @see #getState

     */

    public enum State {

        /**

          线程状态:一个线程还未启动的转台

         * Thread state for a thread which has not yet started.

         */

        NEW,

        /**

          正在运行的线程状态,一个线程在运行中在 java 虚拟机中但是可能等待资源

         * 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,

        /**

          线程状态等待由于调用下面中的一个方法

          wait 超市

          其他线程的 join     

          被锁

         * Thread state for a waiting thread.

         * A thread is in the waiting state due to calling one of the

         * following methods:

         *

         *   {@link Object#wait() Object.wait} with no timeout

         *   {@link #join() Thread.join} with no timeout

         *   {@link LockSupport#park() LockSupport.park}

         *

         *

         * A thread in the waiting state is waiting for another thread to

         * perform a particular action.

         *例如,一个线程被调用了 wait 在一个 object 上,指导其他线程调用 notify 或者 notifyAll 在这个 object 上,一个线程被调用了 join 为了登台这个线程被中断

         * For example, a thread that has called Object.wait()

         * on an object is waiting for another thread to call

         * Object.notify() or Object.notifyAll() on

         * that object. A thread that has called Thread.join()

         * 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:

         *

         *   {@link #sleep Thread.sleep}

         *   {@link Object#wait(long) Object.wait} with timeout

         *   {@link #join(long) Thread.join} with timeout

         *   {@link LockSupport#parkNanos LockSupport.parkNanos}

         *   {@link LockSupport#parkUntil LockSupport.parkUntil}

         *

         */

        TIMED_WAITING,

        /**线程被中断了,或者这个线程已经完全运行结束了

         * Thread state for a terminated thread.

         * The thread has completed execution.

         */

        TERMINATED;

    }

    /**

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

    }

    // Added in JSR-166

    /**

     * Interface for handlers invoked when a Thread abruptly

     * terminates due to an uncaught exception.

     * When a thread is about to terminate due to an uncaught exception

     * the Java Virtual Machine will query the thread for its

     * UncaughtExceptionHandler using

     * {@link #getUncaughtExceptionHandler} and will invoke the handler's

     * uncaughtException method, passing the thread and the

     * exception as arguments.

     * If a thread has not had its UncaughtExceptionHandler

     * explicitly set, then its ThreadGroup object acts as its

     * UncaughtExceptionHandler. If the ThreadGroup object

     * has no

     * special requirements for dealing with the exception, it can forward

     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler

     * default uncaught exception handler}.

     *

     * @see #setDefaultUncaughtExceptionHandler

     * @see #setUncaughtExceptionHandler

     * @see ThreadGroup#uncaughtException

     * @since 1.5

     */

    @FunctionalInterface

    public interface UncaughtExceptionHandler {

        /**

         * Method invoked when the given thread terminates due to the

         * given uncaught exception.

         * Any exception thrown by this method will be ignored by the

         * Java Virtual Machine.

         * @param t the thread

         * @param e the exception

         */

        void uncaughtException(Thread t, Throwable e);

    }

    // null unless explicitly set

    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;

    // null unless explicitly set

    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    /**

     * Set the default handler invoked when a thread abruptly terminates

     * due to an uncaught exception, and no other handler has been defined

     * for that thread.

     *

     * Uncaught exception handling is controlled first by the thread, then

     * by the thread's {@link ThreadGroup} object and finally by the default

     * uncaught exception handler. If the thread does not have an explicit

     * uncaught exception handler set, and the thread's thread group

     * (including parent thread groups)  does not specialize its

     * uncaughtException method, then the default handler's

     * uncaughtException method will be invoked.

     * By setting the default uncaught exception handler, an application

     * can change the way in which uncaught exceptions are handled (such as

     * logging to a specific device, or file) for those threads that would

     * already accept whatever "default" behavior the system

     * provided.

     *

     * Note that the default uncaught exception handler should not usually

     * defer to the thread's ThreadGroup object, as that could cause

     * infinite recursion.

     *

     * @param eh the object to use as the default uncaught exception handler.

     * If null then there is no default handler.

     *

     * @throws SecurityException if a security manager is present and it

     *         denies {@link RuntimePermission}

     *         ("setDefaultUncaughtExceptionHandler")

     *

     * @see #setUncaughtExceptionHandler

     * @see #getUncaughtExceptionHandler

     * @see ThreadGroup#uncaughtException

     * @since 1.5

     */

    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {

        SecurityManager sm = System.getSecurityManager();

        if (sm != null) {

            sm.checkPermission(

                new RuntimePermission("setDefaultUncaughtExceptionHandler")

                    );

        }

         defaultUncaughtExceptionHandler = eh;

     }

    /**

     * Returns the default handler invoked when a thread abruptly terminates

     * due to an uncaught exception. If the returned value is null,

     * there is no default.

     * @since 1.5

     * @see #setDefaultUncaughtExceptionHandler

     * @return the default uncaught exception handler for all threads

     */

    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){

        return defaultUncaughtExceptionHandler;

    }

    /**

     * Returns the handler invoked when this thread abruptly terminates

     * due to an uncaught exception. If this thread has not had an

     * uncaught exception handler explicitly set then this thread's

     * ThreadGroup object is returned, unless this thread

     * has terminated, in which case null is returned.

     * @since 1.5

     * @return the uncaught exception handler for this thread

     */

    public UncaughtExceptionHandler getUncaughtExceptionHandler() {

        return uncaughtExceptionHandler != null ?

            uncaughtExceptionHandler : group;

    }

    /**

     * Set the handler invoked when this thread abruptly terminates

     * due to an uncaught exception.

     * A thread can take full control of how it responds to uncaught

     * exceptions by having its uncaught exception handler explicitly set.

     * If no such handler is set then the thread's ThreadGroup

     * object acts as its handler.

     * @param eh the object to use as this thread's uncaught exception

     * handler. If null then this thread has no explicit handler.

     * @throws  SecurityException  if the current thread is not allowed to

     *          modify this thread.

     * @see #setDefaultUncaughtExceptionHandler

     * @see ThreadGroup#uncaughtException

     * @since 1.5

     */

    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {

        checkAccess();

        uncaughtExceptionHandler = eh;

    }

    /**

     * Dispatch an uncaught exception to the handler. This method is

     * intended to be called only by the JVM.

     */

    private void dispatchUncaughtException(Throwable e) {

        getUncaughtExceptionHandler().uncaughtException(this, e);

    }

    /**

     * Removes from the specified map any keys that have been enqueued

     * on the specified reference queue.

     */

    static void processQueue(ReferenceQueue> queue,

                             ConcurrentMapextends

                             WeakReference>, ?> map)

    {

        Referenceextends Class> ref;

        while((ref = queue.poll()) != null) {

            map.remove(ref);

        }

    }

    /**

     *  Weak key for Class objects.

     **/

    static class WeakClassKey extends WeakReference> {

        /**

         * 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> 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;

    /* Some private helper methods */

    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);

}

  • 代码
    467 引用 • 586 回帖 • 9 关注
  • 线程
    122 引用 • 111 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • abitmean

    有点意思就行了

    27 关注
  • 宕机

    宕机,多指一些网站、游戏、网络应用等服务器一种区别于正常运行的状态,也叫“Down 机”、“当机”或“死机”。宕机状态不仅仅是指服务器“挂掉了”、“死机了”状态,也包括服务器假死、停用、关闭等一些原因而导致出现的不能够正常运行的状态。

    13 引用 • 82 回帖 • 60 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    75 引用 • 258 回帖 • 624 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 75 关注
  • 996
    13 引用 • 200 回帖 • 11 关注
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    209 引用 • 358 回帖
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 5 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    8 引用 • 30 回帖 • 410 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 1 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    76 引用 • 1737 回帖 • 1 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 483 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 478 关注
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    77 引用 • 430 回帖
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 4 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    53 引用 • 40 回帖 • 1 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 400 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 747 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 8 关注
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    93 引用 • 899 回帖 • 1 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 772 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 604 关注
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • 自由行
    4 关注
  • 分享

    有什么新发现就分享给大家吧!

    248 引用 • 1795 回帖 • 1 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    238 引用 • 224 回帖
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖 • 2 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    6 引用 • 63 回帖 • 4 关注