在本文中,我们将详细讨论Java中的核心概念 - 线程的生命周期。
我们将使用快速说明的图表,当然还有实际的代码片段,以便在线程执行期间更好地理解这些状态。
在Java语言中,多线程是由Thread的核心概念驱动的。在他们的生命周期中,线程会经历各种状态:
该java.lang.Thread的类包含一个静态枚举-它定义了它的潜在状态。在任何给定时间点,线程只能处于以下状态之一:
所有这些状态都在上图中列出; 现在我们来详细讨论其中的每一个。
一个新的 线程(或出生线程),是指已创建,但尚未启动的线程。直到我们使用start()方法启动它之前,它一直处于这种状态。
下面的代码片段显示了一个新创建的处于NEW状态的线程:
Runnable runnable = new NewState();
Thread t = new Thread(runnable);
Log.info(t.getState());
由于我们还没有开始提到的线程,所以t.getState()方法打印出来:
NEW
当我们创建一个新线程并在其上调用start()方法时,它将从NEW移至RUNNABLE状态。处于此状态的线程正在运行或准备运行,但它们正在等待系统中的资源分配。
在多线程环境中,Thread-Scheduler(它是JVM的一部分)为每个线程分配固定时间量。所以它会运行一段时间,然后将控制权交给其他RUNNABLE线程。
例如,让我们将t.start()方法添加到我们以前的代码并尝试访问其当前状态:
Runnable runnable = new NewState();
Thread t = new Thread(runnable);
t.start();
Log.info(t.getState());
该代码很可能会将输出返回为:
RUNNABLE
请注意,在这个例子中,并不总是保证当我们的控件达到t.getState()时,它仍然处于RUNNABLE状态。
可能会发生它由Thread-Scheduler立即调度并可能完成执行。在这种情况下,我们可能会得到不同的结果。
一个线程当前没有资格运行时处于BLOCKED状态。它在等待监视器锁定时尝试访问由其他某个线程锁定的代码段时进入此状态。
我们试着重现这个状态:
public class BlockedState {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new DemoThreadB());
Thread t2 = new Thread(new DemoThreadB());
t1.start();
t2.start();
Thread.sleep(1000);
Log.info(t2.getState());
System.exit(0);
}
}
class DemoThreadB implements Runnable {
@Override
public void run() {
commonResource();
}
public static synchronized void commonResource() {
while(true) {
// Infinite loop to mimic heavy processing
// 't1' won't leave this method
// when 't2' try to enters this
}
}
}
在这个代码中:
处于这种状态,我们调用t2.getState()并获取输出:
BLOCKED
线程在等待其他线程执行特定操作时处于WAITING状态。 根据JavaDocs,任何线程都可以通过调用以下三种方法之一来进入该状态:
请注意,在wait()和join()中 - 我们没有定义任何超时期限,因为该方案在下一节中介绍。
我们有一个单独的教程,详细讨论了wait(),notify()和notifyAll()的用法。
现在,让我们尝试重现这个状态:
public class WaitingState implements Runnable {
public static Thread t1;
public static void main(String[] args) {
t1 = new Thread(new WaitingState());
t1.start();
}
public void run() {
Thread t2 = new Thread(new DemoThreadWS());
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
}
}
class DemoThreadWS implements Runnable {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
Log.info(WaitingState.t1.getState());
}
}
让我们来讨论一下我们在做什么:
这里的输出如你所期望的那样:
WAITING
当线程正在等待另一个线程在规定的时间内执行特定操作时,该线程处于TIMED_WAITING状态。
根据JavaDocs,有五种方法将线程置于TIMED_WAITING状态:
现在,我们试着快速重现这个状态:
public class TimedWaitingState {
public static void main(String[] args) throws InterruptedException {
DemoThread obj1 = new DemoThread();
Thread t1 = new Thread(obj1);
t1.start();
// The following sleep will give enough time for ThreadScheduler
// to start processing of thread t1
Thread.sleep(1000);
Log.info(t1.getState());
}
}
class DemoThread implements Runnable {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
}
}
在这里,我们创建并启动了一个线程t1,它以5秒的超时时间进入睡眠状态; 输出将是:
TIMED_WAITING
这是死亡线程的状态。当它完成执行或异常终止时,它处于TERMINATED状态。
让我们尝试在下面的例子中达到这个状态:
ublic class TerminatedState implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new TerminatedState());
t1.start();
// The following sleep method will give enough time for
// thread t1 to complete
Thread.sleep(1000);
Log.info(t1.getState());
}
@Override
public void run() {
// No processing in this block
}
}
在这里,虽然我们已经启动了线程t1,但下一个语句Thread.sleep(1000)为t1提供了足够的时间来完成,因此该程序给出了如下输出:
TERMINATED
在本教程中,我们了解了Java中线程的生命周期。我们查看了由Thread.State枚举定义的所有七个状态,并用快速示例复制了它们。
虽然代码片段几乎可以在每台机器上提供相同的输出,但在某些特殊情况下,我们可能会得到一些不同的输出,因为无法确定线程调度程序的确切行为。
http://blog.xqlee.com/article/416.html