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

【JAVA】多线程基础:线程生命周期与状态切换(31) Java多线程是程序执行的最小单元,允许同时执行多个任务,提升效率和资源利用率。其生命周期包括新建、就绪、运行、阻塞、等待、超时等待和终止状态,状态间通过不同方法切换。多线程适用于提高性能(如并行处理数据)和异步操作(如文件下载、网络请求)。实际应用中,多线程可用于文件下载(将文件分块并行下载)和网络爬虫(多线程爬取网页)。通过合理使用多线程,可以显著提升程序的执行效率和用户体验。 阅读详情

一、前提

最近有点懒散,没什么比较有深度的产出。刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期、状态切换以及线程的上下文切换等等。编写本文的时候,使用的JDK版本是11。

二、Java线程的实现

在JDK1.2之后,Java线程模型已经确定了基于操作系统原生线程模型实现。因此,目前或者今后的JDK版本中,操作系统支持怎么样的线程模型,在很大程度上决定了Java虚拟机的线程如何映射,这一点在不同的平台上没有办法达成一致,虚拟机规范中也未限定Java线程需要使用哪种线程模型来实现。线程模型只对线程的并发规模和操作成本产生影响,对于Java程序来说,这些差异是透明的。

对应Oracle Sun JDK或者说Oracle Sun JVM而言,它的Windows版本和Linux版本都是使用一对一的线程模型实现的(如下图所示)。

也就是一条Java线程就映射到一条轻量级进程(Light Weight Process)中,而一条轻量级线程又映射到一条内核线程(Kernel-Level Thread)。我们平时所说的线程,往往就是指轻量级进程(或者说我们平时新建的java.lang.Thread就是轻量级进程实例)。前面推算这个线程映射关系,可以知道,我们在应用程序中创建或者操作的java.lang.Thread实例最终会映射到系统的内核线程,如果我们恶意或者实验性无限创建java.lang.Thread实例,最终会影响系统的正常运行甚至导致系统崩溃(可以在Windows开发环境中做实验,确保内存足够的情况下使用死循环创建和运行java.lang.Thread实例)。

线程调度方式包括两种,协同式线程调度和抢占式线程调度。

线程调度方式描述劣势优势
协同式线程调度线程的执行时间由线程本身控制,执行完毕后主动通知操作系统切换到另一个线程上某个线程如果不让出CPU执行时间可能会导致整个系统崩溃实现简单,没有线程同步的问题
抢占式线程调度每个线程由操作系统来分配执行时间,线程的切换不由线程自身决定实现相对复杂,操作系统需要控制线程同步和切换不会出现一个线程阻塞导致系统崩溃的问题

Java线程最终会映射为系统内核原生线程,所以Java线程调度最终取决于系操作系统,而目前主流的操作系统内核线程调度基本都是使用抢占式线程调度。也就是可以死记硬背一下:Java线程是使用抢占式线程调度方式进行线程调度的。

很多操作系统都提供线程优先级的概念,但是由于平台特性的问题,Java中的线程优先级和不同平台中系统线程优先级并不匹配,所以Java线程优先级可以仅仅理解为“建议优先级”,通俗来说就是java.lang.Thread#setPriority(int newPriority)并不一定生效,有可能Java线程的优先级会被系统自行改变。

三、Java线程的状态切换

Java线程的状态可以从java.lang.Thread的内部枚举类java.lang.Thread$State得知:

public enum State {
	NEW,
	    RUNNABLE,
	    BLOCKED,
	    WAITING,
	    TIMED_WAITING,
	    TERMINATED;
}

这些状态的描述总结成图如下:

线程状态之间关系切换图如下:

1. NEW状态

API注释:

/**
 * Thread state for a thread which has not yet started.
 *
 */
NEW,

线程实例尚未启动时候的线程状态。

一个刚创建而尚未启动(尚未调用Thread#start()方法)的Java线程实例的就是出于NEW状态。

public class ThreadState {
	public static void main(String[] args) throws Exception {
		Thread thread = new Thread();
		System.out.println(thread.getState());
	}
}
// 输出结果
NEW

2. RUNNABLE状态

API注释:

/**
 * 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.
 */
RUNNABLE,

可运行状态下线程的线程状态。可运行状态下的线程在Java虚拟机中执行,但它可能执行等待操作系统的其他资源,例如处理器。

当Java线程实例调用了Thread#start()之后,就会进入RUNNABLE状态。RUNNABLE状态可以认为包含两个子状态:READY和RUNNING。

  • READY:该状态的线程可以被线程调度器进行调度使之更变为RUNNING状态。
  • RUNNING:该状态表示线程正在运行,线程对象的run()方法中的代码所对应的的指令正在被CPU执行。

当Java线程实例Thread#yield()方法被调用时或者由于线程调度器的调度,线程实例的状态有可能由RUNNING转变为READY,但是从线程状态Thread#getState()获取到的状态依然是RUNNABLE。例如:

public class ThreadState1 {
	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(()-> {
			while (true){
				Thread.yield();
			}
		}
		);
		thread.start();
		Thread.sleep(2000);
		System.out.println(thread.getState());
	}
}
// 输出结果
RUNNABLE

3. WAITING状态

API注释:

/**
 * 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 {@code Object.wait()}
 * on an object is waiting for another thread to call
 * {@code Object.notify()} or {@code Object.notifyAll()} on
 * that object. A thread that has called {@code Thread.join()}
 * is waiting for a specified thread to terminate.
 */
WAITING,

等待中线程的状态。一个线程进入等待状态是由于调用了下面方法之一:
不带超时的Object#wait()
不带超时的Thread#join()
LockSupport.park()
一个处于等待状态的线程总是在等待另一个线程进行一些特殊的处理。
例如:一个线程调用了Object#wait(),那么它在等待另一个线程调用对象上的Object#notify()或者Object#notifyAll();一个线程调用了Thread#join(),那么它在等待另一个线程终结。

WAITING是无限期的等待状态,这种状态下的线程不会被分配CPU执行时间。当一个线程执行了某些方法之后就会进入无限期等待状态,直到被显式唤醒,被唤醒后,线程状态由WAITING更变为RUNNABLE然后继续执行。

RUNNABLE转换为WAITING的方法(无限期等待)WAITING转换为RUNNABLE的方法(唤醒)
Object#wait()Object#notify()或者Object#notifyAll()
Thread#join()-
LockSupport.part()LockSupport.unpart(thread)

其中Thread#join()方法相对比较特殊,它会阻塞线程实例直到线程实例执行完毕,可以观察它的源码如下:

public final void join() throws InterruptedException {
	join(0);
}
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;
		}
	}
}

可见Thread#join()是在线程实例存活的时候总是调用Object#wait()方法,也就是必须在线程执行完毕isAlive()为false(意味着线程生命周期已经终结)的时候才会解除阻塞。

基于WAITING状态举个例子:

public class ThreadState3 {
	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(()-> {
			LockSupport.park();
			while (true){
				Thread.yield();
			}
		}
		);
		thread.start();
		Thread.sleep(50);
		System.out.println(thread.getState());
		LockSupport.unpark(thread);
		Thread.sleep(50);
		System.out.println(thread.getState());
	}
}
// 输出结果
WAITING
RUNNABLE

4. TIMED WAITING状态

API注释:

/**
* 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>
*/
TIMED_WAITING,

定义了具体等待时间的等待中线程的状态。一个线程进入该状态是由于指定了具体的超时期限调用了下面方法之一:
Thread.sleep()
带超时的Object#wait()
带超时的Thread#join()
LockSupport.parkNanos()
LockSupport.parkUntil()

TIMED WAITING就是有限期等待状态,它和WAITING有点相似,这种状态下的线程不会被分配CPU执行时间,不过这种状态下的线程不需要被显式唤醒,只需要等待超时限期到达就会被VM唤醒,有点类似于现实生活中的闹钟。

RUNNABLE转换为TIMED WAITING的方法(有限期等待)TIMED WAITING转换为RUNNABLE的方法(超时解除等待)
Object#wait(timeout)-
Thread#sleep(timeout)-
Thread#join(timeout)-
LockSupport.parkNanos(timeout)-
LockSupport.parkUntil(timeout)-

举个例子:

public class ThreadState4 {
	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(()-> {
			try {
				Thread.sleep(1000);
			}
			catch (InterruptedException e) {
				//ignore
			}
		}
		);
		thread.start();
		Thread.sleep(50);
		System.out.println(thread.getState());
		Thread.sleep(1000);
		System.out.println(thread.getState());
	}
}
// 输出结果
TIMED_WAITING
TERMINATED

5. BLOCKED状态

API注释:

/**
* 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}.
*/
BLOCKED,

此状态表示一个线程正在阻塞等待获取一个监视器锁。如果线程处于阻塞状态,说明线程等待进入同步代码块或者同步方法的监视器锁或者在调用了Object#wait()之后重入同步代码块或者同步方法。

BLOCKED状态也就是阻塞状态,该状态下的线程不会被分配CPU执行时间。线程的状态为BLOCKED的时候有两种可能的情况:

A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method

  • 线程正在等待一个监视器锁,只有获取监视器锁之后才能进入synchronized代码块或者synchronized方法,在此等待获取锁的过程线程都处于阻塞状态。

reenter a synchronized block/method after calling Object#wait()

  • 线程X步入synchronized代码块或者synchronized方法后(此时已经释放监视器锁)调用Object#wait()方法之后进行阻塞,当接收其他线程T调用该锁对象Object#notify()/notifyAll(),但是线程T尚未退出它所在的synchronized代码块或者synchronized方法,那么线程X依然处于阻塞状态(注意API注释中的reenter,理解它场景2就豁然开朗)。

针对上面的场景1举个简单的例子:

public class ThreadState6 {
	private static final Object MONITOR = new Object();
	public static void main(String[] args) throws Exception {
		Thread thread1 = new Thread(()-> {
			synchronized (MONITOR){
				try {
					Thread.sleep(Integer.MAX_VALUE);
				}
				catch (InterruptedException e) {
					//ignore
				}
			}
		}
		);
		Thread thread2 = new Thread(()-> {
			synchronized (MONITOR){
				System.out.println("thread2 got monitor lock...");
			}
		}
		);
		thread1.start();
		Thread.sleep(50);
		thread2.start();
		Thread.sleep(50);
		System.out.println(thread2.getState());
	}
}
// 输出结果
BLOCKED

针对上面的场景2举个简单的例子:

public class ThreadState7 {
	private static final Object MONITOR = new Object();
	private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	public static void main(String[] args) throws Exception {
		System.out.println(String.format("[%s]-begin...", F.format(LocalDateTime.now())));
		Thread thread1 = new Thread(() -> {
			synchronized (MONITOR) {
				System.out.println(String.format("[%s]-thread1 got monitor lock...", F.format(LocalDateTime.now())));
				try {
					Thread.sleep(1000);
					MONITOR.wait();
				}
				catch (InterruptedException e) {
					//ignore
				}
				System.out.println(String.format("[%s]-thread1 exit waiting...", F.format(LocalDateTime.now())));
			}
		}
		);
		Thread thread2 = new Thread(() -> {
			synchronized (MONITOR) {
				System.out.println(String.format("[%s]-thread2 got monitor lock...", F.format(LocalDateTime.now())));
				try {
					MONITOR.notify();
					Thread.sleep(2000);
				}
				catch (InterruptedException e) {
					//ignore
				}
				System.out.println(String.format("[%s]-thread2 releases monitor lock...", F.format(LocalDateTime.now())));
			}
		}
		);
		thread1.start();
		thread2.start();
		// 这里故意让主线程sleep 1500毫秒从而让thread2调用了Object#notify()并且尚未退出同步代码块,确保thread1调用了Object#wait()
		Thread.sleep(1500);
		System.out.println(thread1.getState());
		System.out.println(String.format("[%s]-end...", F.format(LocalDateTime.now())));
	}
}
// 某个时刻的输出如下:
[2019-06-20 00:30:22]-begin...
[2019-06-20 00:30:22]-thread1 got monitor lock...
[2019-06-20 00:30:23]-thread2 got monitor lock...
BLOCKED
[2019-06-20 00:30:23]-end...
[2019-06-20 00:30:25]-thread2 releases monitor lock...
[2019-06-20 00:30:25]-thread1 exit waiting...

场景2中:

  • 线程2调用Object#notify()后睡眠2000毫秒再退出同步代码块,释放监视器锁。
  • 线程1只睡眠了1000毫秒就调用了Object#wait(),此时它已经释放了监视器锁,所以线程2成功进入同步块,线程1处于API注释中所述的reenter a synchronized block/method的状态。
  • 主线程睡眠1500毫秒刚好可以命中线程1处于reenter状态并且打印其线程状态,刚好就是BLOCKED状态。

这三点看起来有点绕,多看几次多思考一下应该就能理解。

6. TERMINATED状态

API注释:

/**
 * Thread state for a terminated thread.
 * The thread has completed execution.
 */
TERMINATED;

终结的线程对应的线程状态,此时线程已经执行完毕。

TERMINATED状态表示线程已经终结。一个线程实例只能被启动一次,准确来说,只会调用一次Thread#run()方法,Thread#run()方法执行结束之后,线程状态就会更变为TERMINATED,意味着线程的生命周期已经结束。

举个简单的例子:

public class ThreadState8 {
	public static void main(String[] args) throws Exception {
		Thread thread = new Thread(() -> {
		}
		);
		thread.start();
		Thread.sleep(50);
		System.out.println(thread.getState());
	}
}
// 输出结果
TERMINATED

四、上下文切换

多线程环境中,当一个线程的状态由RUNNABLE转换为非RUNNABLE(BLOCKED、WAITING或者TIMED_WAITING)时,相应线程的上下文信息(也就是常说的Context,包括CPU的寄存器和程序计数器在某一时间点的内容等等)需要被保存,以便线程稍后恢复为RUNNABLE状态时能够在之前的执行进度的基础上继续执行。而一个线程的状态由非RUNNABLE状态进入RUNNABLE状态时可能涉及恢复之前保存的线程上下文信息并且在此基础上继续执行。这里的对线程的上下文信息进行保存和恢复的过程就称为上下文切换(Context Switch)。

线程的上下文切换会带来额外的性能开销,这包括保存和恢复线程上下文信息的开销、对线程进行调度的CPU时间开销以及CPU缓存内容失效的开销(线程所执行的代码从CPU缓存中访问其所需要的变量值要比从主内存(RAM)中访问响应的变量值要快得多,但是线程上下文切换会导致相关线程所访问的CPU缓存内容失效,一般是CPU的L1 Cache和L2 Cache,使得相关线程稍后被重新调度到运行时其不得不再次访问主内存中的变量以重新创建CPU缓存内容)。

在Linux系统中,可以通过vmstat命令来查看全局的上下文切换的次数,例如:

$ vmstat 1

对于Java程序的运行,在Linux系统中也可以通过perf命令进行监视,例如:

$ perf stat -e cpu-clock,task-clock,cs,cache-reference,cache-misses java YourJavaClass

参考资料中提到Windows系统下可以通过自带的工具perfmon(其实也就是任务管理器)来监视线程的上下文切换,实际上笔者并没有从任务管理器发现有任何办法查看上下文切换,通过搜索之后发现了一个工具:Process Explorer。运行Process Explorer同时运行一个Java程序并且查看其状态:

因为打了断点,可以看到运行中的程序的上下文切换一共7000多次,当前一秒的上下文切换增量为26(因为笔者设置了Process Explorer每秒刷新一次数据)。

五、监控线程状态

如果项目在生产环境中运行,不可能频繁调用Thread#getState()方法去监测线程的状态变化。JDK本身提供了一些监控线程状态的工具,还有一些开源的轻量级工具如阿里的Arthas,这里简单介绍一下。

1. 使用jvisualvm

jvisualvm是JDK自带的堆、线程等待JVM指标监控工具,适合使用于开发和测试环境。它位于JAVA_HOME/bin目录之下。

其中线程Dump的按钮类似于下面要提到的jstack命令,用于导出所有线程的栈信息。

2. 使用jstack

jstack是JDK自带的命令行工具,功能是用于获取指定PID的Java进程的线程栈信息。例如本地运行的一个IDEA实例的PID是11376,那么只需要输入:

jstack 11376

另外,如果想要定位具体Java进程的PID,可以使用jps命令。

3. 使用JMC

JMC也就是Java Mission Control,它也是JDK自带的工具,提供的功能要比jvisualvm强大,包括MBean的处理、线程栈以及线程状态查看、飞行记录器等等。

六、小结

理解Java线程状态的切换和一些监控手段,更有利于日常开发多线程程序,对于生产环境出现问题,通过监控线程的栈信息能够快速定位到问题的根本原因(通常来说,目前比较主流的MVC应用都是通过一个线程处理一个单独的请求,当请求出现阻塞的时候,导出对应处理请求的线程基本可以定位到阻塞的精准位置,如果使用消息队列例如RabbitMQ,消费者线程出现阻塞也可以利用相似的思路解决)。

Java_supermanNO1:专注于Java开发技术的研究与知识分享!

————END————

  • 点赞(编辑不易,感谢您的支持)
  • …
  • 转发(分享知识,传播快乐)
  • …
  • 关注(每天更新Java开发技术)
  • …
因时机器人-灵巧手配置方案(Ubuntu18.04) 阅读详情

相关推荐

告别手动刷金币:零代码配置实现番茄小说自动化任务

本文详细介绍如何利用零代码配置工具实现番茄小说自动化任务,告别手动刷金币的烦恼。通过冰狐智能辅助工具的可视化配置和元数据复用功能,用户无需编程基础即可快速设置自动签到、观看广告等任务流程,大幅提升效率并避免断签风险。

weixin_42522953的博客 295

Java线程生命周期详解

Java中的线程生命周期是多线程开发的核心概念。了解线程的生命周期以及它们如何进行状态转换对于编写有效且无错误的多线程程序至关重要。

沐雨风栉 6840

P+F--r2000激光雷达slam技术实现

P+F--r2000激光雷达slam技术实现

majingming123的博客 1667

Java基础夯实——2.4 线程的生命周期

java线程生命周期

m0_60235638的博客 1571

iOS自动化之打包-xcodebuild命令行打包.app并安装到ios模拟器

xcode xcodebuild xcrun ios模拟器 iOS UI自动化测试 ios自动打包安装到ios模拟器

z12347891的博客 5073

KEPServerEX 6 之 GE Ethernet 连接FANUC ROBOT机器人实战

GE Fanuc是GE公司控制系统部门的一部分,成立于1998年。其主要业务涵盖工业自动化、控制系统、PLC和组态软件等领域。其产品可用于包括自动化、过程自动化、国防、汽车制造、通讯、医疗和航空航天等各种工业领域2009 8月 GE和FANUC今天宣布两家公司已同意解除合资企业GE FANUC自动化公司。通过以上历史,GE Ethernet Driver 当下还支持对接FANUC ROBOT机器人 就不奇怪了。

-雲飛兄-博客 1790

一篇文章掌握Java线程的生命周期(含快速掌握技巧)

新建(NEW)就绪(RUNNABLE)阻塞(BLOCKED)等待(WAITING)超时等待(TIMED_WAITING)终止(TERMINATED)记忆技巧(※※)。表示线程从新建到终止的流程。接着记忆WAITING和,这两者都表示线程处于 “等待状态”,只是 TIMED_WAITING 只会等待一段时间,而 WAITING 会无限等待,直到被唤醒。最后就是BLOCKED状态,这个状态可以理解为线程正在尝试获取锁,没有获取到就会处于 BLOCKED 状态。

2401_82656016的博客 1956

虚幻商城 Fab 免费资产自动化入库

Fab 商城的所有的免费资产自动化入库

一碗清深的博客 3630

Java 线程生命周期

Java线程生命周期是一个重要的概念,在多线程编程中非常常见。了解线程状态的转换条件以及如何使用Java代码来实现线程状态的转换是非常重要的。同时,我们还可以使用Java的线程相关API来控制线程的状态,并确保线程的正确执行。希望本篇博客能够帮助你更好地理解Java线程生命周期。

hj1993的博客 831

Python爬虫实战:全自动采集银行理财产品收益率数据

本文通过Playwright动态爬虫技术,成功实现了对银行理财产品收益率数据的实时采集,并通过 Pandas 数据清洗、SQLite 存储、调度自动化等模块,构建了一个可扩展的银行理财数据抓取系统。理财非儿戏,数据做决策。掌握银行收益信息是我们迈向理性投资的第一步。希望这套工具对你有所帮助!

2201_76125261的博客 1154

基于Python实现学习进度跟踪系统

{{ task }}: {{ "%.1f"|format(hours) }}小时

寒寒豆豆软件公司的博客 195

JAVA中的生命周期

线程的生命周期可以分为七种。

yxm2633669081的博客 1365

29、几何形态测量学在蝴蝶翅膀研究中的应用

本博客介绍了几何形态测量学在花斑木蛱蝶(Pararge aegeria)翅膀研究中的应用,探讨了环境因素对蝴蝶翅膀大小和形状的影响。通过选择合适的地标并采用Procrustes分析方法,研究揭示了不同景观类型下翅膀形状的差异及其潜在的适应性意义。文章还讨论了发育可塑性在飞行形态变异中的作用,并比较了几何形态测量学与其他传统方法的优势。最后提出了未来研究方向,包括多因素综合分析、发育机制探索及长期生态监测,为理解蝴蝶的适应性进化提供了重要线索。

ff678的博客 107

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

前提最近有点懒散,没什么比较有深度的产出。刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期、状态切换以及线程的上下文切换等等。编写...

Throwable 4093

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

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

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

dsq_MaDing的博客 807

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Java线程的6种状态及切换(透彻讲解)

Java中线程的状态分为6种。 1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。 2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中...

诚 6万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java 线程的六种状态与完整生命周期详解

在 Java 中,线程状态(Thread State)是由枚举定义的,NEWstart()start()WAITINGnotify()join()也就是说,线程的生命周期可以分为五个主要阶段:新建、就绪、运行、阻塞和终止。线程在运行过程中会根据状态的变化在这些阶段之间切换。

m0_73748193的博客 1093

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

前提最近有点懒散,没什么比较有深度的产出。刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期、状态切换以及线程的上下文切换等等。编写本...

Java知音 460

线程池 waiting on condition_Java线程生命周期与状态切换

前提最近有点懒散,没什么比较有深度的产出。刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期、状态切换以及线程的上下文切换等等。编写本文的时候,使用的JDK版本是11。Java线程的实现在「JDK1.2之后」,Java线程模型已经确定了基于操作系统原生线程模型实现。因此,目前或者今后的JDK版本中,操作系统支持怎么样的线程模型,在很大程度上决定...

weixin_28846179的博客 7374

java线程的五大状态,阻塞状态详解

一、状态简介 一个线程的生命周期里有五大状态,分别是: 新生 就绪 运行 死亡 运行后可能遇到的阻塞状态 二、相关方法 2.1 新生状态 Thread t = new Thread(); 正如我们前面所说的,一个线程开始之后有自己的内存空间,这些工作空间和主内存进行交互,从主内存拷贝数据到工作空间。 当这个语句执行的时候,线程创建,开辟工作空间,也就是线程进入了新生状态。 2.2 就绪状态 普通情况,一旦调用了: t.start(); start 方法被调用,线程立即进入了就绪状态,表示这个线程具

LifeGoesOn 1万+

线程的状态与切换

线程的状态与切换

scj1022的博客 1459

java中,线程的生命周期

java中,线程的生命周期 一、什么是线程? 见之前写的。 当线程启动后(线程对象调用start方法),它不能一直"独占"着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。 二、线程的生命周期是什么? 在线程的生命周期中: 它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)五种状态。 新建...

SeniorShen的博客 1万+

多线程篇-6--线程生命周期(线程生命周期,线程状态切换,线程中断,及常用的线程方法)

线程中断是Java中的一种机制,用于请求线程停止其当前工作并退出。中断是一种协作机制,而不是强制性的终止。这意味着被中断的线程可以选择如何处理中断请求,通常会通过检查中断标志来决定是否终止当前操作。

weisian的博客 3万+
上一篇: 面试中的被问到Spring,我们该怎么去回答
下一篇: Spring Cloud微服务接口这么多怎么调试
Java_supermanNO1
博客等级 码龄7年 1170粉丝 329原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值