亲宝软件园·资讯

展开

Java线程生命周期

 sofia   人气:0

前言:

在本文中,我们将详细讨论Java中的一个核心概念——线程的生命周期。我们将使用一个快速的图解,当然还有实用的代码片段来更好地理解线程执行期间的这些状态。

Java多线程

在Java语言中,多线程是由线程的核心概念驱动的。线程在其生命周期中会经历各种状态:

Java中线程的生命周期

java.lang.Thread类包含一个静态枚举,它定义了它的潜在状态。在任何给定的时间点内,线程只能处于以下状态之一:

上图涵盖了所有这些状态;现在让我们详细讨论其中的每一项。

NEW

新线程(或出生线程)是已创建但尚未启动的线程。在我们使用start()方法启动它之前,它一直保持此状态。

以下代码段显示了新创建的处于新状态的线程:

Runnable runnable = new NewState();
Thread t = new Thread(runnable);
Log.info(t.getState());

由于我们尚未启动上述线程,因此方法t.getState()会打印:

NEW

Runnable

当我们创建了一个新线程并对其调用start()方法时,它将从NEW状态移动到RUNNABLE状态。处于此状态的线程正在运行或准备运行,但它们正在等待来自系统的资源分配。

在多线程环境中,线程调度程序(JVM的一部分)为每个线程分配固定的时间量。因此,它会运行一段特定的时间,然后将控制权交给其他可运行的线程。

例如,让我们将t.start()方法添加到前面的代码中,并尝试访问其当前状态:

Runnable runnable = new NewState();
Thread t = new Thread(runnable);
t.start();
Log.info(t.getState());

此代码很可能返回以下输出:

RUNNABLE

请注意:在本例中,并不总是保证在控件到达t.getState()时,它仍处于可运行状态。

线程调度器可能会立即对其进行调度,并可能完成执行。在这种情况下,我们可能会得到不同的输出。

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 enter this
        }
    }
}

在此代码中:

处于这种状态,我们称之为t2.getState()并获取输出,如下所示:

BLOCKED

Waiting

线程在等待其他线程执行特定操作时处于等待状态。

根据JavaDocs,任何线程都可以通过调用以下三种方法中的任何一种进入这种状态:

请注意,在wait()join()中,我们没有定义任何超时时间,因为下一节将介绍该场景。

现在,让我们尝试重现这种状态:

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

当线程等待另一个线程在规定的时间内执行特定操作时,该线程处于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

这是死线程的状态。当它完成执行或异常终止时,它处于终止状态。

让我们在以下示例中尝试实现此状态:

public 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

除了线程状态之外,我们还可以检查isAlive()方法以确定线程是否处于活动状态。例如,如果我们在此线程上调用isAlive()方法:

Assert.assertFalse(t1.isAlive());

结论

在本文中,我们学习了Java中线程的生命周期。我们查看了线程定义的所有六个状态。陈述enum并用快速示例再现它们。虽然代码片段在几乎每台机器上都会给出相同的输出,但在某些例外情况下,我们可能会得到一些不同的输出,因为无法确定线程调度器的确切行为。

加载全部内容

相关教程
猜你喜欢
用户评论