Java线程生命周期与状态切换详解

Java线程生命周期与状态切换详解

一、线程生命周期概述

在 Java 中,线程是程序执行的最小单位,每个线程都有其自身的生命周期。线程的生命周期包含了一系列的状态,线程会在这些状态之间进行切换,直至最终结束。理解线程的生命周期和状态切换对于编写高效、稳定的多线程程序至关重要。

二、线程的六种状态

Java 中 Thread 类定义了一个枚举类型 State,它包含了线程的六种状态:

1. NEW(新建状态)

当创建一个 Thread 对象时,线程就处于新建状态。此时,线程仅仅是在 Java 虚拟机(JVM)中被分配了内存,还没有开始执行任何代码。
示例代码:

public class NewStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("线程正在执行");
        });
        // 此时线程处于 NEW 状态
        System.out.println(thread.getState()); 
    }
}

2. RUNNABLE(可运行状态)

当调用线程的 start() 方法后,线程进入可运行状态。处于可运行状态的线程可能正在 Java 虚拟机中执行,也可能在等待操作系统分配 CPU 时间片。
示例代码:

public class RunnableStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("线程正在执行");
        });
        thread.start();
        // 此时线程处于 RUNNABLE 状态
        System.out.println(thread.getState()); 
    }
}

3. BLOCKED(阻塞状态)

当线程试图获取一个对象的锁,而该锁正被其他线程持有,线程就会进入阻塞状态。在阻塞状态下,线程不会占用 CPU 时间,直到它获取到锁。
示例代码:

public class BlockedStateExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                System.out.println("线程 2 获取到锁");
            }
        });

        thread1.start();
        thread2.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 此时线程 2 处于 BLOCKED 状态
        System.out.println(thread2.getState()); 
    }
}

4. WAITING(等待状态)

当线程调用了 Object.wait()Thread.join()LockSupport.park() 方法后,线程会进入等待状态。处于等待状态的线程会无限期地等待,直到其他线程调用 Object.notify()Object.notifyAll()LockSupport.unpark() 方法来唤醒它。
示例代码:

public class WaitingStateExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 此时线程处于 WAITING 状态
        System.out.println(thread.getState()); 
    }
}

5. TIMED_WAITING(计时等待状态)

当线程调用了 Thread.sleep(long millis)Object.wait(long timeout)Thread.join(long millis)LockSupport.parkNanos(long nanos)LockSupport.parkUntil(long deadline) 方法后,线程会进入计时等待状态。在计时等待状态下,线程会等待指定的时间,时间一到就会自动唤醒。
示例代码:

public class TimedWaitingStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        thread.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 此时线程处于 TIMED_WAITING 状态
        System.out.println(thread.getState()); 
    }
}

6. TERMINATED(终止状态)

当线程的 run() 方法执行完毕,或者线程因为异常而终止时,线程进入终止状态。处于终止状态的线程已经结束了其生命周期,不能再重新启动。
示例代码:

public class TerminatedStateExample {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("线程正在执行");
        });
        thread.start();
        try {
            // 等待线程执行完毕
            thread.join(); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 此时线程处于 TERMINATED 状态
        System.out.println(thread.getState()); 
    }
}

三、线程状态切换

线程的状态会根据不同的操作和条件进行切换,下面是常见的状态切换情况:

1. NEW -> RUNNABLE

当调用线程的 start() 方法时,线程从新建状态切换到可运行状态。

2. RUNNABLE -> BLOCKED

当线程试图获取一个被其他线程持有的锁时,线程从可运行状态切换到阻塞状态。

3. RUNNABLE -> WAITING

当线程调用 Object.wait()Thread.join()LockSupport.park() 方法时,线程从可运行状态切换到等待状态。

4. RUNNABLE -> TIMED_WAITING

当线程调用 Thread.sleep(long millis)Object.wait(long timeout)Thread.join(long millis)LockSupport.parkNanos(long nanos)LockSupport.parkUntil(long deadline) 方法时,线程从可运行状态切换到计时等待状态。

5. BLOCKED -> RUNNABLE

当线程获取到之前被其他线程持有的锁时,线程从阻塞状态切换到可运行状态。

6. WAITING -> RUNNABLE

当其他线程调用 Object.notify()Object.notifyAll()LockSupport.unpark() 方法唤醒等待的线程时,线程从等待状态切换到可运行状态。

7. TIMED_WAITING -> RUNNABLE

当计时等待的时间到期时,线程从计时等待状态切换到可运行状态。

8. RUNNABLE -> TERMINATED

当线程的 run() 方法执行完毕,或者线程因为异常而终止时,线程从可运行状态切换到终止状态。

四、总结

Java 线程的生命周期和状态切换是多线程编程中的重要概念。了解线程的不同状态以及它们之间的切换条件,有助于我们更好地控制线程的执行流程,避免线程安全问题,从而编写出高效、稳定的多线程程序。在实际开发中,可以根据具体的需求,合理地使用线程的各种方法来实现线程状态的切换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值