Thread 源码详解

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

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

}

  • 代码
    466 引用 • 631 回帖 • 9 关注
  • 线程
    122 引用 • 111 回帖 • 3 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 625 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 3 关注
  • abitmean

    有点意思就行了

    29 关注
  • Mobi.css

    Mobi.css is a lightweight, flexible CSS framework that focus on mobile.

    1 引用 • 6 回帖 • 733 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 376 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    209 引用 • 2031 回帖
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    167 引用 • 1513 回帖
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 261 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    408 引用 • 3574 回帖
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 633 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 175 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    125 引用 • 169 回帖 • 1 关注
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    351 引用 • 1814 回帖
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 43 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 483 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 302 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    198 引用 • 550 回帖
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖
  • Solidity

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

    3 引用 • 18 回帖 • 399 关注
  • CodeMirror
    1 引用 • 2 回帖 • 129 关注
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 27 关注
  • GraphQL

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

    4 引用 • 3 回帖 • 9 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 531 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 167 关注
  • ZeroNet

    ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。

    1 引用 • 21 回帖 • 638 关注