Java线程的状态操作

本文详细介绍了Java中线程状态的控制方法,包括sleep用于线程休眠、join用于等待线程结束、yield让出CPU时间片、interrupt中断线程,以及不同阻塞状态的含义。

1. 线程的状态操作概述

        默认情况下,一个处于就绪状态的线程何时执行,由操作系统的调度器来决定。但是在很多实际的应用场景中,经常需要开发者人为的对线程的状态进行控制。例如,控制某个线程在其他线程执行完成后再执行,或者控制某个线程休眠一段时间等。

        Java提供了多个可以操作线程状态的方法。例如:

  • sleep():控制某个线程休眠一段时间
  • join():控制某个线程等待另一个线程执行完成后再执行
  • yield():控制一个线程从运行状态切换到就绪状态
  • interrupt():向线程发送一个中断通知

2. sleep 方法

        Thread 的静态方法 sleep 用于使当前线程进入阻塞状态,语法为:

static void sleep(long ms)

        该方法会使当前线程进入阻塞状态指定毫秒,当阻塞指定毫秒后,当前线程会重新进入 Runnable 状态,等待分配时间片.

        该方法声明会抛出一个InterruptException,因此在使用该方法时需要捕获这个异常。

        编写代码,测试sleep方法,实现要求如下:

        代码示意如下:

import java.time.LocalTime;
import java.util.concurrent.TimeUnit;

public class SleepDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread( () -> {
            try{
                System.out.println("正在运行的线程名称:"
                        +Thread.currentThread().getName()
                        +" 开始时间 = " + LocalTime.now());
                // 延时2秒
                // Thread.sleep(2000);
                TimeUnit.SECONDS.sleep(2); // 1.5新语法 可读性更好
                System.out.println("正在运行的线程名称:"+
                        Thread.currentThread().getName()+
                        " 结束时间 = " + LocalTime.now());
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        } );
        System.out.println("主线程开始时间 = " + LocalTime.now());
        t1.start();
        System.out.println("主线程结束时间 = " + LocalTime.now());
    }
}

3. join 方法

        Thread 的 方法 join 用于等待当前线程结束,语法如下:

void join()

        该方法声明抛出InterruptException。

import java.util.concurrent.TimeUnit;

public class JoinDemo {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRun2(), "t1");
        Thread t2 = new Thread(new MyRun2(), "t2");
        Thread t3 = new Thread(new MyRun2(), "t3");
        t1.start();
        // 主线程等待t1线程死亡或等待2秒后向下执行启动t2线程
        try {
            // t1.join(2000);
            TimeUnit.SECONDS.timedJoin(t1, 2); // 1.5新语法
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.start();
        // 主线程等待t1线程死亡后再向下执行启动t3线程的代码
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t3.start();
        // 主线程等待t1线程、t2线程和t3线程死亡后再向下执行
        try {
            t1.join();
            t2.join();
            t3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("All threads are dead, exiting main thread");
    }
}
// 多个线程复用的场景,使用Runnable接口实现类
class MyRun2 implements Runnable{
    @Override
    public void run() {
        System.out.println("Threadstarted:::"
                +Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread ended:::"
                +Thread.currentThread().getName());
    }
}

4. yield 方法

        Thread 的静态方法 yield 语法如下:

static void yield()

        该方法用于使当前线程主动让出当次CPU时间片回到Runnable状态,等待分配时间片。比如对正在运行中的线程1调用 yield 方法,则进入就绪状态:

        编写代码,测试yield方法,代码示意如下:

public class YieldDemo {
    public static void main(String[] args){
        Runnable run = () -> {
            String name = Thread.currentThread().getName();
            for (int i = 0;i<8;i++){
                System.out.println(name+":"+i);
                if(i == 5){
                    // 主动释放CUP使用权
                    Thread.yield();
                }
            }
        };
        Thread t1 = new Thread(run,"Thread1");
        t1.start();
        Thread t2 = new Thread(run,"Thread2");
        t2.start();
    }	
}

5. interrupt方法

        Thread 的静态方法 interrupt 用于设置线程的中断状态。该方法试图将目标线程的中断标志设置为true,最终结果取决于线程的当前状态。

        对于当前处于运行状态的线程,调用interrupt方法后,线程的中断标识设置为true。如下图所示:

        interrupt中断休眠示例,编写代码,测试使用interrupt方法中断休眠。代码示意如下:

import java.util.concurrent.TimeUnit;

public class InterruptDemo1 {
    public static void main(String args[]) {
        Thread thread = new Thread(() -> {
            System.out.println("线程启动了");
            try {
                TimeUnit.MINUTES.sleep(3);
            } catch (InterruptedException e) {
                System.out.println("抛出异常对象: "+e);
            }
            System.out.println("线程结束了");
        });
        thread.start(); // 启动子线程
        try {
            // 主线程休眠5秒
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 在线程阻塞时抛出一个中断信号
        // 这样线程就得以退出阻塞状态
        thread.interrupt();
    }
}

        通过interrupted标识终止线程示例,可以通过循环确认某个线程的interrupted标识来控制一个线程的运行状态。

import java.util.concurrent.TimeUnit;

public class InterruptDemo2 {
    public static void main(String args[]) {
        Thread thread = new Thread(() -> {
            Thread cThread = Thread.currentThread();
            System.out.println("线程启动了");
            // while循环持续检测线程的中断标识
            while (!cThread.isInterrupted()){
                System.out.println("Thread say...");
            }
            System.out.println("线程结束了");
        });
        thread.start(); // 启动子线程
        try {
            // 主线程休眠1毫秒
            TimeUnit.MILLISECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 向运行中的子线程发送一个中断通知
        thread.interrupt();
    }
}

6. 其他阻塞状态

        线程的阻塞状态可细分为:等待阻塞、同步阻塞和其他阻塞。前两者和线程的同步相关,将在后续的课程中介绍。其他阻塞是指因调用线程的sleep方法或join方法而导致的线程阻塞,如下图所示:

        输入/输出请求是指与其他程序或者与操作系统的输入/输出接口进行交互的场景,由于被访问的数据可能需要一定的准备工作,输入/输出操作是线程阻塞的常见原因。

理解Java线程的状态及其转换是掌握Java并发编程的关键,正确管理线程状态、合理利用同步机制,可有效提高Java应用的性能和响应速度。在Java中,线程状态指的是JVM层面定义的6种状态,而非操作系统中定义的5种基本状态,这是因为在源码中定义Thread State时就定义了这6种状态 [^1][^2]。 这6种Java线程状态如下: - **NEW**:线程刚被创建,但还未调用`start`方法,此时线程处于初始状态。 - **RUNNABLE**:可运行状态,当一个线程使用`start`方法时,就会从NEW状态转变为RUNNABLE状态。该状态下的线程可能正在Java虚拟机中执行,也可能在等待操作系统中的其他资源(如处理器) [^4][^5]。 - **WAITING**:等待状态,线程因为不带参数的`join()`或者`wait()`而阻塞等待,当等待的那个线程运行结束或者`wait`被`notify`唤醒时,线程会从WAITING状态转变为RUNNABLE状态或者TERMINATED状态 [^5]。 - **TIMED_WAITING**:限时等待状态,线程因为带参数的`join(1000)`或者`wait(1000)`等方法阻塞等待,当等待的时间到达时,线程会从TIMED_WAITING状态转变为RUNNABLE状态或者TERMINATED状态 [^5]。 - **BLOCKED**:阻塞状态,线程由于锁竞争而导致阻塞,当这个线程获得锁之后,会从BLOCKED状态转变为RUNNABLE状态 [^5]。 - **TERMINATED**:终止状态,当一个线程运行完`run`方法时,就会从RUNNABLE状态进入TERMINATED状态 [^5]。 以下是一个简单的Java代码示例,展示了线程状态的变化: ```java public class ThreadStateExample { public static void main(String[] args) { Thread thread = new Thread(() -> { try { // 线程休眠,进入TIMED_WAITING状态 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); // 输出线程初始状态,应为NEW System.out.println("线程初始状态: " + thread.getState()); // 启动线程,进入RUNNABLE状态 thread.start(); System.out.println("线程启动后的状态: " + thread.getState()); try { // 主线程等待子线程执行完毕 thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } // 子线程执行完毕,进入TERMINATED状态 System.out.println("线程执行完毕后的状态: " + thread.getState()); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangyan_1010

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值