多线程1——Thread和Runnable
Thread
创建线程的方法:
//1.继承Thread
class MyThread extends Thread{
@override
public void run(){
for(int I=0;i<100; I++){
System.out.println(i);
}
}
}
MyThread myThread = new MyThread();
myThread.start();
//2.实现Runnable
class MyTask implements Runnable{
@override
public void run(){
for(int I=0;i<100; I++){
System.out.println(i);
}
}
}
new Thread(new MyTask()).start();
这是两种创建多线程的方法。个人跟喜欢称其为两种创建任务和提交任务给线程进行执行的方法。
参考C++中创建线程的一种方法:
uintptr_t _beginthreadex( // NATIVE CODE
void *security, //线程安全属性
unsigned stack_size, //线程的栈大小
unsigned ( *start_address )( void * ),//线程函数
void *arglist, //传递到线程函数中的参数
unsigned initflag, //线程初始化标记
unsigned *thrdaddr //线程ID
);
#include "stdafx.h"
#include<iostream>
#include<Windows.h>
#include<process.h>
using namespace std;
//C++中创建线程的方法是:首先创建一个线程的主入口函数,在主入口函数中执行任务
//之后使用_beginthreadex创建线程,该线程所需执行的任务是ThreadProc
unsigned int _stdcall ThreadProc(LPVOID lpParameter)
{
cout << "thread function ThreadProc!\n";
return 0;
}
int main()
{
_beginthreadex(NULL, 0, ThreadProc, 0, 0, NULL);
Sleep(1000);
cout << "main end!\n";
system("pause");
return 0;
}
C++中创建线程的方法是:首先创建一个函数A,在函数中执行任务。之后A作为参数使用_beginthreadex创建线程,该线程所需执行的任务是A。
同样,java中也是如此。在实现Runnable或者在继承Thread中重写run方法,既是提供执行任务的函数。之后实例化Thread,调用start()函数,就是分配一个线程,在该线程中运行run方法,执行任务。
两种创建线程的方法更倾向于使用第二种。因为其对于理解任务和提交任务给线程比较容易。
每当看到下面这种形式的代码时: new Thread(runnable).start()
并且你希望获得一种更加灵活的执行策略时,请考虑使用Excutor来代替
引用自《Java并发编程实战》
Runable
@FunctionalInterface
public interface Runnable {
/**
当一个实现了Runnable接口的类被传递到一个线程的时候,启动线程后,线程将会调用run方法
*/
public abstract void run();
}
Thread
Thread方法实现了Runnable接口。
我们通常接触的Thread类的方法以下这几种。
- start()和run()
- sleep()
- suspend() 和 resume()
- stop()
- interrupted()
- yield()
- join()
set(Default)UncaughtExceptionHandler()
start()和run()
//run方法就是我们在继承Thread的时候需要重写的方法。
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* <p>
* The result is that two threads are running concurrently: the
* current thread (which returns from the call to the
* <code>start</code> method) and the other thread (which executes its
* <code>run</code> method).
* <p>
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*启动一个线程,并在线程中执行run方法。
一个线程只能启动一次,再次启动会抛出IllegalThreadStateException
* @exception IllegalThreadStateException if the thread was already
* started.
* @see #run()
* @see #stop()
*/
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".
* 这种启动线程的方法并不是VM启动main线程或者system线程的方法
*/
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();
这是启动线程的start()方法。我们能从中注意到的点是:
- 一个线程只能启动一次,在start()方法中通过线程的状态来判断线程是否已经被启动。线程启动后将执行run方法。
- start()方法是一个同步的方法。防止同时启动多个线程的情况。
但是start0()方法是一个本地方法。在Thread类中有很多方法都是本地方法。
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
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
* 当sleep的线程被中断,则抛出InterruptedException
*/
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
* <i>interrupted status</i> 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);
}
sleep()方法又是本地方法。有两点:
- 调用Sleep()意味使当前线程休眠。
public void test(){
MyTask task = new MyTask();
Thread myThread = new MyThread(task);
myThread.start();
myThread.sleep(5000);
Thread.sleep(5000);//两者的所用一致,都是使当前线程休眠5秒钟,而不是让myThread休眠5秒。
}
当前线程被休眠后,状态从RUNNABLE变成TIMED_WAITING.处于TIMED_WAITING状态的线程如果被中断则会抛出InterruptedException。另外处于被中断状态的线程如果调用sleep,也会抛出InterruptedException
suspend()和resume()
suspend和resume的方法体都比较简单。
/**
* Suspends this thread.
* <p>
* First, the <code>checkAccess</code> method of this thread is called
* with no arguments. This may result in throwing a
* <code>SecurityException </code>(in the current thread).
* <p>
* If the thread is alive, it is suspended and makes no further
* progress unless and until it is resumed.
* 挂起线程。首先使用checkAccess来检查当前线程是否可以更改这个线程。
* 在thread的源码中经常看到两个单词,一个是current thread,一个是this thread。
* myThread.suspend()
* 调用myThread.suspend()这句话的线程为当前线程。myThread为this thread。
* 如果checkAccess不抛出异常,则线程会一直暂停直到resume()方法被调用
* @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 <code>resume</code>, deadlock results. Such
* deadlocks typically manifest themselves as "frozen" processes.
* For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
* 这个方法是被废弃的。一个线程被暂停之后不会释放所拥有的锁。因此其他需要资源的线程将一直阻塞。另外如果一个线程必须持有锁才能调用resume来恢复该线程的运行,这就会造成死锁。
*
*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
/**
* Resumes a suspended thread.
* <p>
* First, the <code>checkAccess</code> method of this thread is called
* with no arguments. This may result in throwing a
* <code>SecurityException</code> (in the current thread).
* <p>
* 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
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
suspend()和resume()方法是一对被废弃的方法。
- 在suspend()后,线程持有的锁不被释放,容易遭成死锁,饥饿。死锁的原因上面已经解释过。当线程由于无法访问它所需要的资源而不能继续执行的时候,就发生了“饥饿”。一个线程持有锁A被暂停,其他需要锁A的线程则被阻塞。
- suspend()的时候,可能会造成数据处于不一致的状态
如果suspend和resume不能用,那么应该使用什么机制来实现线程的暂停和恢复呢?
wait和notify
stop()方法
/**
* Forces the thread to stop executing.
* 强行终止一个线程
* <p>
* If there is a security manager installed, its <code>checkAccess</code>
* method is called with <code>this</code>
* as its argument. This may result in a
* <code>SecurityException</code> being raised (in the current thread).
* <p>
* 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 <code>checkPermission</code> method (with a
* <code>RuntimePermission("stopThread")</code> argument) is called in
* addition.
* Again, this may result in throwing a
* <code>SecurityException</code> (in the current thread).
* 终止线程前需要对安全机制进行检查。这一步没有了解。
* <p>
* The thread represented by this thread is forced to stop whatever
* it is doing abnormally and to throw a newly created
* <code>ThreadDeath</code> object as an exception.
* <p>
* 线程会被强行终止,不管它在做什么,而且会抛出一个ThreadDeath的异常。
* It is permitted to stop a thread that has not yet been started.
* If the thread is eventually started, it immediately terminates.
* <p>
* 也允许终止一个还没有启动的线程。
* An application should not normally try to catch
* <code>ThreadDeath</code> unless it must do some extraordinary
* cleanup operation (note that the throwing of
* <code>ThreadDeath</code> causes <code>finally</code> clauses of
* <code>try</code> statements to be executed before the thread
* officially dies). If a <code>catch</code> clause catches a
* <code>ThreadDeath</code> object, it is important to rethrow the
* object so that the thread actually dies.
* 一个应用不应该尝试捕捉ThreadDeath,除非它必须做些清理的工。ThreadDeath的抛出会导致finnally语句块在线程正式终止前执行。
* <p>
* 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
* <code>ThreadDeath</code>.
*一个顶级的错误处理器,当抛出的异常时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
* <code>ThreadDeath</code> 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 <code>stop</code> 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 <code>interrupt</code> method should be used to
* interrupt the wait.
* For more information, see
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
* 这个方法不是安全的,因此被废弃。一个线程stop之后会释放其拥有的所有锁。有可能会导致被锁保护的共享状态变量出现不一致的状态。而其他的线程将会读取到不符合不变性条件的共享数据。抛去stop方法,我们应该使用一个状态变量来指示一个线程是否应该被终止。目标线程应该有规律的检查这个状态变量,并在需要停止的时候停止。如果目标线程处于等待状态,则应该使用interrupt方法在中断等待状态。
*/
@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
* <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
*/
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
stop方法也是被放弃的方法,那我们应该采用什么机制来停止一个线程呢
1.设置一个“请求停止标志”,让目标线程轮循该变量。
2.使用中断
在停止一个方法的同时又什么需要注意的事项吗?
如何取消不支持中断的阻塞方法?什么是不支持中断的阻塞方法?
如何取消线程池中的任务?(我们没有办法拿到具体执行任务的线程)
interrupt()
/**
* Interrupts this thread.
* 中断线程
* 1.安全检查
* 2.因为调用object的wait(),wait(long),wait(long,int),或者thread类的join(),join(long),join(long,int),sleep(long),sleep(long,int)方法
* 线程被阻塞,则线程的中断状态被清除,且抛出InterruptedException异常
* 3.如果线程因为java.nio.channels.InterruptibleChannel上的一个IO操作而被阻塞,则调用interrupt()会使channel关闭,线程的中断状态被设置,并且线程接收到java.nio.channels.ClosedByInterruptException异常
* 4.如果线程因为java.nio.channels.Selector被阻塞,则调用interrupt()方法会设置线程的中断状态,并且是selection操作返回一个非零的值,就好像调用了java.nio.channels.Selector的wakeup()方法一样。
* 5.如果不是上述情况的任何一种,中断状态会被设置。
* <p> 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.
*
* <p> 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}.
*
* <p> 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}.
*
* <p> 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.
*
* <p> If none of the previous conditions hold then this thread's interrupt
* status will be set. </p>
*
* <p> 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
* <i>interrupted status</i> 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).
*
* <p>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 <code>true</code> if the current thread has been interrupted;
* <code>false</code> otherwise.
* @see #isInterrupted()
* @revised 6.0
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* Tests whether this thread has been interrupted. The <i>interrupted
* status</i> of the thread is unaffected by this method.
* 验证线程是否被中断,中断状态不被清除。
* <p>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 <code>true</code> if this thread has been interrupted;
* <code>false</code> 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);
利用interrupt()方法、在run方法中判断线程是否被终止、以及合适的异常处理会很容易的停止一个线程。在Java中没有一种安全的抢占式方法来停止一个线程,因此也就没有安全的抢占式方法来停止任务。只有一些协作式机制,使得请求取消的任务和代码都遵循一种协商好的协议。
yeild()
/**
* 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.
*对线程调度器的一个提示,当前线程希望让出处理器。线程调度器可以忽略这个消息。
* <p> 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.
* yield是一种试图提高线程间相互进度的方法,否则会出现CPU的过度使用(???)
* yield需要和详细的性能测试和基准测试结合起来,以保证可以实现想要的效果
* <p> 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.
* 很少有使用这个方法的情况。只有在测试的情况下。这个方法因为可能会提高竞态条件而重现bug.当设计并发控制构造器的时候,也可以使用yield。
*/
public static native void yield();
并发代码中的大多数错误都是一些低概率的时间,因此在测试并发错误的时候需要反复地执行许多次,但有些方法可以提高这些错误的概率。在前面提到过,在多处理器系统上,如果处理器的数量少于活动线程的数量,那么与单处理器系统或者包含多个树立起的系统相比,将会产生更多的交替行为(上下文切换)。同样,如果在不同的处理器数量、操作系统以及处理器架构的系统上进行测试,就可以发现那些在特定运行环境下中才会出现的问题
有一种有用的方法可以提高交替操作的数量,以便能更有效的搜索程序的状态空间:在访问共享状态的操作中,使用Thread.yield将产生更多的上下文切换(这项技术的有效性与具体的平台相关,因为JVM可以将Thread.yield作为一个空操作。如果使用一个睡眠时间较短的sleep,那么虽然更慢些,但却更可靠。)
引用自《Java并发编程实战》
join()
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
* 等待这个线程结束。在millis毫秒内,线程结束,则当前线程继续向下运行。如果在millis毫秒以内,线程没有结束,则当前线程在millis时继续执行。
* <p> 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.
* join方法循环的调用isAlive和wait方法来实现当前线程持有this线程的锁,然后等待this线程。如果this线程执行完毕,则调用notifyAll()来通知当前线程。
* 其实一个应用最好不要调用thread实例上的wait,notify,notifyAll方法。
* 如果任何线程终端了当前线程,终端状态将会被清除,并且抛出异常InterruptedException。
* @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
* <i>interrupted status</i> 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.
*
* <p> 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
* <i>interrupted status</i> 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);
}
因为wait会释放锁,所以join方法也会释放锁。
join方法有几个有趣的例子。请参考《Java多线程核心技术》
set(Default)UncaughtExceptionHandler()
set(Default)UncaughtExceptionHandler()方法关于线程的异常处理。之后介绍。
线程的状态
在start()方法中,需要通过判断线程的状态来确定是否是重新启动线程
许多抛出interruptedException的方法,几乎都与阻塞或者等待有关。
sleep(long)方法将RUNNABLE状态转换为TIMED_WAITING状态
线程有几种状态?
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.
* 在JVM中运行,但是有可能正在等待处理器
*/
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}.
* 阻塞状态。
* 一个线程在等待一个锁(原因是因为想要进入一个同步方法或同步代码块,或者在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.
* 等待状态:
* 一个线程处于等待状态有几种原因:
* 1.object.wait()
* 2.thread.join()
* 3.lockSupport.park()
* 处于等待状态的线程需要其他线程执行特定的操作才能转换成RUNNABLE状态。
* wait()方法需要等待notify()或者notifyAll
* join()方法需要等待另一个线程执行完毕
* park()需要等待lockSupport.unpark()
*/
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>
* 限时等待状态
* 1.sleep()
* 2.wait(long)
* 3.join(long)
* 4.lockSupport.parkNanos()
* 5.lockSupport.parkUntil()
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
* 终止状态
*/
TERMINATED;
}
线程状态图