在我们稍稍脱离初学程序的阶段时,可能会开始使用许多框架工具,抑或是写WebApp时使用Servlet API,都会发现去了解架构是很重要的事情,了解架构才有办法让我们开发软件的时候知道自己在哪里,其中有一部分是去了解软件的生命周期。
我觉得这是满有趣的一件事,软件这种纯粹人工的事物理应没有生命,但在我们人类的理解上,生命周期是最恰当的词语来形容了。
今天就要来谈谈执行绪(Thread)的生命周期(Life Cycle)。
我个人在初学Java时,学到执行绪真的是满头痛的,不是很能在脑海中有明确的画面去想像,不过在了解到执行绪的生命周期後,让我有豁然开朗的感觉。
来上图!
当我们实作Runnable介面或继承Thread类别,覆写run()方法後,就要创建Thread实例来启动该执行绪:
Thread thread01 = new Thread(() -> {
for(int i = 0; i < 10; i++){
System.out.println(i);
}
});
thread01.start();
当呼叫了Thread的start()後,就是开始了执行绪的生命周期了,thread会进到Runnable的状态,这个阶段就像是被放进一个等待区一样,而电脑的CPU就像是工作人员会来叫号,被叫到的thread就可以离开等待区,进到工作区占用电脑CPU资源开始跑run()方法;要注意这边的叫号是随机的,或者可以透过Java API提供的setPriority()方法设定执行绪被叫号的优先权。
当执行绪的run()方法内容执行完毕後,thread就会进入Terminated的状态,相当於这个执行绪的生命到了尽头,就算在thread.start()一遍也没办法再跑一次,甚至还会吐出IllegalThreadStateException例外。
除了Runnable以及Running的阶段外,有些情况执行绪会进到类似隔离区的Blocked状态,通常是当执行绪在跑输入输出的程序时就会进到Blocked状态,等输入输出完成後才会重新回到等待区Runnable等待CPU叫号;也可能是我们主动在某个流程中呼叫执行绪的sleep()方法,就会强制该执行绪进到Blocked状态;也可能是在设定了synchronized的程序中等待物件内部锁(intrinsic lock),也会进到Blocked状态。
以上是执行绪生命周期的整体概念,下面接着要来说说程序码上执行绪的执行状况。
public static void Main(String[] args){
Thread thread01 = new Thread(() -> {
for(int i = 0; i < 10; i++){
System.out.println("thread01 " + i);
}
});
Thread thread02 = new Thread(() -> {
for(int i = 0; i < 10; i++){
System.out.println("thread02 " + i);
}
});
thread01.setDaemon(true);
thread02.start();
thread01.start();
}
我们初学常常测试程序码使用的Main方法,其实本身就是一个thread,称为main thread;当Main方法执行完时,main thread也就Terminated了,JVM随之关闭。
而当我们在Main方法中去启动其他执行绪时,我们的main thread会等到这些执行绪都执行完毕後,才会进到Terminated状态;不过有一种设定叫做Daemon,如上面的程序码范例,我们设定了thread01.setDaemon(true),被设定为Daemon的执行绪不会被main thread等待,main thread跑完了就会直接进到Terminated状态,所以上面的程序码跑完会发现thread01有时候会跑不到9,但是thread02一定会跑到9。
在JavaScript中,想要控制流程,就要设计流程中的条件。 条件判断 if...else 望文生...
本篇大纲:合并图表绘制关键、图表画面与互动效果、本次使用资料、图表绘制 今天的一天一图表,我们要来...
上回说到歌伦比亚大学制作的类似AR眼镜的装置,今天!还是歌伦比亚大学 1996-1997年 他们在1...
前情提要 方函式也有流程分工,参数负责收东西 方函式:(电话再响)喂,你说参数不在东西谁要收吗?直接...
我们可以利用上次相同的题目来做此双因子变异数分析。 某间面包店的面包师傅想研究不同配方做出的面包所销...