多线程基础(二): Thread源码分析


前面已经对java中Thread的生命周期进行了分析,现在看看Thread的源码。

1.类结构及其成员变量

1.1 类结构

Thread类实现了Runnable,实际上我们说过,需要起一个线程的话,需要继承Thread或者实现Runnable接口。实际上都是实现了Runnable接口。

/**
 * A <i>thread</i> is a thread of execution in a program. The Java
 * Virtual Machine allows an application to have multiple threads of
 * execution running concurrently.
 * <p>
 * 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 <code>Thread</code> 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.
 * <p>
 * When a Java Virtual Machine starts up, there is usually a single
 * non-daemon thread (which typically calls the method named
 * <code>main</code> of some designated class). The Java Virtual
 * Machine continues to execute threads until either of the following
 * occurs:
 * <ul>
 * <li>The <code>exit</code> method of class <code>Runtime</code> has been
 *     called and the security manager has permitted the exit operation
 *     to take place.
 * <li>All threads that are not daemon threads have died, either by
 *     returning from the call to the <code>run</code> method or by
 *     throwing an exception that propagates beyond the <code>run</code>
 *     method.
 * </ul>
 * <p>
 * There are two ways to create a new thread of execution. One is to
 * declare a class to be a subclass of <code>Thread</code>. This
 * subclass should override the <code>run</code> method of class
 * <code>Thread</code>. 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:
 * <hr><blockquote><pre>
 *     class PrimeThread extends Thread {
 *         long minPrime;
 *         PrimeThread(long minPrime) {
 *             this.minPrime = minPrime;
 *         }
 *
 *         public void run() {
 *             // compute primes larger than minPrime
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote><hr>
 * <p>
 * The following code would then create a thread and start it running:
 * <blockquote><pre>
 *     PrimeThread p = new PrimeThread(143);
 *     p.start();
 * </pre></blockquote>
 * <p>
 * The other way to create a thread is to declare a class that
 * implements the <code>Runnable</code> interface. That class then
 * implements the <code>run</code> method. An instance of the class can
 * then be allocated, passed as an argument when creating
 * <code>Thread</code>, and started. The same example in this other
 * style looks like the following:
 * <hr><blockquote><pre>
 *     class PrimeRun implements Runnable {
 *         long minPrime;
 *         PrimeRun(long minPrime) {
 *             this.minPrime = minPrime;
 *         }
 *
 *         public void run() {
 *             // compute primes larger than minPrime
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote><hr>
 * <p>
 * The following code would then create a thread and start it running:
 * <blockquote><pre>
 *     PrimeRun p = new PrimeRun(143);
 *     new Thread(p).start();
 * </pre></blockquote>
 * <p>
 * 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.
 * <p>
 * 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 {
    
}

如上是Thread的源码。
其注释大意为:thread是程序中执行的线程,JVM允许在一个程序中分配多个线程并发执行。
每个线程都有一个优先级,具有较高优先级的线程优先于优先级较低的线程执行,每个线程也可以标记为守护线程,也可以不标记为守护线程。当运行在某个线程中的代码创建一个新的线程的对象时,新的线程优先级最初设置为与创建的线程的优先级相等。当且仅当创建线程是守护线程的时候,被创建的新线程才是守护线程。
当jvm启动的时候,通常有一个单独的非守护线程,通常用调用main方法所在的类命名。java虚拟机会继续执行线程,直到出现如下情况:

  • 运行时Runtime调用exit方法,安全管理器允许执行退出操作。
  • 所有不是守护线程的线程都died,要么从调用run的方法返回,要么抛出一个传播到run方法之外的异常。

通常有两种方式创建一个线程,一种是继承Thread类,子类应该重写run方法。然后子类的实例是可分配的并启动。例如,计算质数的线程大于指定值可写成:

class PrimeThread extends Thread {
    long minPrime;
    PrimeThread(long minPrime) {
         this.minPrime = minPrime;
     }

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

然后通过如下代码来创建线程:

PrimeThread p = new PrimeThread(143);
p.start();

创建线程的另外一种方法是申明一个类实现Runnable接口。然后这个类实现run方法。类的实例在此后分配,在创建时做为Thread的参数传递给Thread,然后启动,看起来如下所示:

class PrimeRun implements Runnable {
   long minPrime;
   PrimeRun(long minPrime) {
       this.minPrime = minPrime;
   }

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

之后通过如下代码创建:

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

每个线程都有一个用于标识的名称,超过一个线程可以有相同的名字,如果名称未指定时创建要给线程,将自动为其生成一个新名称。

1.2 成员变量

其常量区代码如下:

private volatile String 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;

/* What will be run. */
private Runnable target;

/* The group of this thread */
private ThreadGroup group;

/* The context ClassLoader for this thread */
private ClassLoader contextClassLoader;

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

/*
 * 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-private state that persists after native thread termination.
 */
private long nativeParkEventPointer;

/*
 * Thread ID
 */
private long tid;

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

其主要成员变量如下:

变量名类型说明
namevolatile String线程名称
priorityint线程的优先级,默认为5,范围1-10
threadQThread
eetoplong
single_stepboolean是否单步执行
daemonboolean守护线程状态,默认为false
stillbornbooleanJVM状态,默认为false
targettarget将被执行的Runnable实现类
groupThreadGroup当前线程的线程组
contextClassLoaderClassLoader这个线程上下文的类加载器
inheritedAccessControlContextAccessControlContext该线程继承的AccessControlContext
threadInitNumberstatic int用于匿名线程的自动编号
threadLocalsThreadLocal.ThreadLocalMap属于此线程的ThreadLocal,这个映射关系通过ThreadLocal维持
inheritableThreadLocalsThreadLocal.ThreadLocalMap这个线程的InheritableThreadLocal,其映射关系通过InheritableThreadLocal维持
stackSizelong此线程的请求的堆栈的大小,如果创建者的请求堆栈大小为0,则不指定堆栈大小,由jvm来自行决定。一些jvm会忽略这个参数。
nativeParkEventPointerlong在本机线程终止后持续存在的jvm私有状态。
tidlong线程的ID
threadSeqNumberstatic long用于生成线程的ID
threadStatusvolatile intjava线程状态,0表示未启动
parkBlockervolatile Object提供给LockSupport调用的参数
blockervolatile Interruptible此线程在可中断的IO操作中被阻塞的对象,阻塞程序的中断方法应该在设置了这个线程中断状态之后被调用

1.3 常量

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

实际上这些常量值是对于线程优先级的常量,最小为1,最大为10,默认值为5。操作系统在线程在运行的过程中会按照优先级来分配时间片。

2.构造方法

2.1 Thread()

空构造函数,发呢配一个新的Thread对象,实际上是调用的init方法。由于Thread大部分代码都是native来实现,因此这个构造函数是通过改变前面的成员变量来实现对Thread各种行为的改变。

/**
 * 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-"+}<i>n</i>, where <i>n</i> is an integer.
 */
public Thread() {
    init(null, null, "Thread-" + nextThreadNum(), 0);
}

2.2 Thread(Runnable target)

/**
 * 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-"+}<i>n</i>, where <i>n</i> 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);
}

此方法是我们通常用Runnable启动线程的方法。
实际上我们穿入的Runnable对象,被放置在了target变量中,之后通过后jvm中启动线程|

2.3 Thread(Runnable target, AccessControlContext acc)

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

在传入Runnable的时候还可以指定AccessControlContext。

2.4 Thread(ThreadGroup group, Runnable target)

/**
 * 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-"+}<i>n</i>, where <i>n</i> 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);
}

使用线程组ThreadGroup。如果有安全管理器,则线程由安全管理器返回 SecurityManager.getThreadGroup()。如果没有安全管理器或者SecurityManager.getThreadGroup()返回为空,则返回当前的线程组。

2.5 Thread(String name)

指定线程的名称:

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

2.6 Thread(ThreadGroup group, String name)

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

2.7 Thread(Runnable target, String name)

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

通过Runnable并指定线程的name。

2.8 Thread(ThreadGroup group, Runnable target, String name)

public Thread(ThreadGroup group, Runnable target, String name) {
    init(group, target, name, 0);
}

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

public Thread(ThreadGroup group, Runnable target, String name,
              long stackSize) {
    init(group, target, name, stackSize);
}

分配一个线程,使其将target做为目标对象,具有name指定的名称,和group指定的线程组。其中,指定StackSize参数能够决定其for循环栈的深度,但是这也由JVM决定,某些JVM这个参数并不能生效。
JVM可以自由的处理stackSize的参数做为建议值,如果指定的值低得不合理,那么可以使用jvm平台的最小值。如果值太高,则可能会使用平台缺省的最大值。虚拟机可以自由地四舍五入指定的值,让到JVM认为是合适的值。
stackSize参数为0则会导致其与Thread(ThreadGroup, Runnable, String)构造器完全一致。
由于这个特性依赖于JVM平台,因此在使用的时候要特别小心,给定线程的stackSize可能因为线程对峙的大小造成不同JRE实现有所不同。鉴于此,可能需要仔细调整堆栈的大小参数,根据JRE要运行程序的实际情况进行调优。

3. native方法

由于Thread大部分逻辑都是由JVM完成,因此核心的方法都是native方法。

//确保registerNatives是<clinit>做的第一件事,这个代码要放在代码的最前面。
private static native void registerNatives();

//返回当前线程
public static native Thread currentThread();

//当前线程在获取CPU执行权之后,让出,之后让等待队列的线程重新竞争。有可能是当前线程再次抢到执行权,也有可能是其他线程。
public static native void yield();

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

//启动
private native void start0();

//测试某个值是否被中断 中断状态根据传入的ClearInterrupted值进行重置
private native boolean isInterrupted(boolean ClearInterrupted);

//测试线程是否是存活状态
public final native boolean isAlive();

//计算线程中的堆栈数,此线程必须被暂停 ,这个方法已不再建议使用
public native int countStackFrames();


//当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
public static native boolean holdsLock(Object obj);

//导出线程堆栈信息
private native static StackTraceElement[][] dumpThreads(Thread[] threads);

//get线程
private native static Thread[] getThreads();

//设置优先级
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);

4.重要的非native方法

4.1 init

线程初始化方法

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc,
                  boolean inheritThreadLocals) {
   //name如果为空,则返回异常,实际上name在其他方法中如果不指定会自动生成,通常为"Thread-" + nextThreadNum()
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }

    this.name = name;
    //指定父线程
    Thread parent = currentThread();
    //安全管理器
    SecurityManager security = System.getSecurityManager();
    //如果线程组为null
    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的线程组
            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 (inheritThreadLocals && parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    /* Stash the specified stack size in case the VM cares */
    //指定stackSize
    this.stackSize = stackSize;

    /* Set thread ID */
    //指定线程id
    tid = nextThreadID();
}

4.2 start

线程启动的方法:

public synchronized void start() {
/**
 * 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 {
    //实际上调用的native方法
    start0();
    //之后修改start的状态
    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 */
    }
}
}

4.3 setDaemon

设置守护线程状态:

public final void setDaemon(boolean on) {
    checkAccess();
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

4.4 checkAccess

检查访问状态:

public final void checkAccess() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkAccess(this);
    }
}

4.5 join

join将当前运行的线程阻塞,之后让join的持有线程执行完之后再继续执行。等待时间为传入的参数。

public final synchronized void join(long millis)
throws InterruptedException {
    //获得当前时间
    long base = System.currentTimeMillis();
    long now = 0;

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

    if (millis == 0) {
    //如果当前线程可用,则调用wait
        while (isAlive()) {
            wait(0);
        }
    } else {
        通过wait方法delay。
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

这个方法提供给另外两个方法调用:

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

其中wait(0)的话,则会一直阻塞,直到notify才会返回。不难发现,join方法底层实际上是wait方法。

4.6 sleep

sleep方法通过native方法实现。

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

其中只是判断了值的范围。

4.7 interrupt

public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();
   锁定之后调用interrupt0
    synchronized (blockerLock) {
        Interruptible b = blocker;
        //如果b不为null则返回
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    //当b为空的情况确保interrupt0一定会被执行。
    interrupt0();
}

4.8 stop方法

stop方法已经过时,不再采用这个方法停止线程,这是因为,stop方法非常粗暴,会导致很多问题,后面详细分析。

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

5.内部类

5.1 Caches

cache缓存了子类安全审计的结果。如果未来要进行使用,采用ConcurrentReferenceHashMap替换。

/** cache of subclass security audit results */
/* Replace with ConcurrentReferenceHashMap when/if it appears in a future
 * release */
private static class Caches {
    //缓存子类安全审计结果
    /** cache of subclass security audit results */
    static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
        new ConcurrentHashMap<>();

    //对审计子类的weak引用进行排队
    /** queue for WeakReferences to audited subclasses */
    static final ReferenceQueue<Class<?>> subclassAuditsQueue =
        new ReferenceQueue<>();
}

5.2 WeakClassKey

弱引用对象的key。

/**
 *  Weak key for Class objects.
 **/
static class WeakClassKey extends WeakReference<Class<?>> {
    /**
     * saved value of the referent's identity hash code, to maintain
     * a consistent hash code after the referent has been cleared
     */
    private final int hash;

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

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

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

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

5.3 State

线程的状态内部枚举类。这个线程的状态有NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED状态。

public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

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

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     *
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * 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:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}

状态的详细描述在前面文章中已经详细介绍。我们重点需要关注这些状态的转换:
线程模型

6.总结

本文分析了Thread的源码。我们可以看出,实际上join方法实际上底层是采用了synchronized和Object的wait方法。另外,停止线程的stop方法已经弃用,我们应该用interrupt()方法。
stop和interrupt方法区别在于:
stop方法会立即杀死线程,不给线程任何暂停的机会,一旦线程持有Lock,那么线程就来不及调用unlock方法,这样就导致其他线程再也不可能获得这个锁。这是非常危险的操作,也是为什么stop方法会被弃用的原因。
interrupt方法则仅仅只是通知线程,线程可以继续执行后续操作,interrupt实际上是一个异常检测的流程。当线程 处于 WAITING、TIMED_WAITING 状态时,如果其他线程调用线程的 interrupt() 方法,会使线程返回到 RUNNABLE 状态,同时线程 的代码会触发 InterruptedException 异常。
此外还有一种主动检测机制,就是通过调用isInterrupted()方法。
最后,我们需要重点掌握线程模型中的6个状态及其转换的过程。这也是我们学习线程的重点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值