java两种多线程,说明java两种实现多线程的方式
3.线程状态
线程状态有很多种,包括新状态、可运行状态、正在运行状态、等待/阻塞/睡眠/监控/挂起状态、死状态5。
1)、新状态
新状态是指线程被实例化时的状态,但是还没有在线程上调用start方法。它还没有准备好运行,更不用说执行线程了。
2)、运行状态
Start()方法启动后,线程从新状态进入runnable状态。操作状态是准备好并可操作但尚未操作的状态。
stat()方法不仅可以进入运行状态,还可以从等待/阻塞/睡眠/监控/挂起状态进入运行状态。例如,当调用sleep()方法时,调用yield(0方法后使用的线程都将进入可运行状态。
可运行状态也可以说是CPU选择线程的状态。的所有线程都没有优先级,前线程和后线程。只要它们处于可运行状态,它们就可以被CPU选择运行。当然,也有可能这个线程处于可运行状态,但不会运行很长时间。这是一个特例。有这样的情况,一个线程总是在运行,比如在一个线程中调用yield()方法,然后进入runnable状态,但是后面的线程还在运行。
3)、运行状态
它是执行线程的当前状态。它可以进入可运行状态和等待/阻塞/失眠/监控/暂停状态,但它只能从可运行状态进入运行状态。
4)、等待/阻塞/睡眠/监控/挂起状态
等待/阻塞/睡眠/监控/暂停状态非常复杂。它是许多状态的集合,但它们都在运行状态和可运行状态之间起着中介作用。如果一个正在运行的线程因为某种原因无法继续运行,比如调用了sleep()方法,被调用了join()方法,这个线程就会从运行状态进入等待/阻塞/睡眠/监控/挂起状态。当sleep()方法结束或者调用join()方法的线程结束时,线程可以再次运行。
除了sleep()、yield()和join()方法之外,进入/被阻塞/睡眠/监视/挂起状态的方法还包括suspend()方法,这意味着一个线程挂起另一个线程。
5)停滞状态
当线程中的run()方法完成时,线程进入死状态。如果对处于死状态的线程使用start()方法,将会发生异常。
4.线程调度
线程调度器是JVM的一部分,它决定在任何给定的时间应该运行哪个线程,并使线程脱离运行状态。线程调度定义了java运行时环境如何交换任务并选择下一个要执行的任务。调度线程是通过priority、sleep()、yield()和join()方法完成的。如前所述,CPU对线程的选择是不确定的,我们可以通过调度知识让线程按照一定的方式运行,但不能完全指定。
1)、优先级
用于确定何时允许线程运行。理论上,高优先级的线程可以比低优先级的线程获得更多的CPU时间。其实CPU时间的长短和很多因素有关,不能单纯用优先级来判断。使用setPriority(int level)方法设置设计线程的优先级。在级别值中,MIN_PRIORITY用于表示最低优先级1;MAX_PRIORITY用来表示最大优先级10;线程的默认优先级是5,即NORM_PRIORITY。
获取当前线程优先级的方法是getPriority(),一般形式是getPriority()。
请看下面的优先级应用程序,它通过执行循环和记录时间来显示优先级:
公共类测试{
public static void main(String[]str){
Thread.currentThread()。setPriority(线程。MAX _ PRIORITY);
MyThread t1=newMyThread(线程。NORM _优先级2);
MyThread t2=newMyThread(线程。NORM _ PRIORITY-2);
t1 . start();
T2 . start();
尝试{
thread . sleep(1000);
} catch(异常e) {
t1 . stop();
T2 . stop();
尝试{
t1 . t . join();
T2 . t . join();
} catch(异常e) {
System.out.println(低优先级线程 T2 . click);
System.out.println(高优先级线程 t1 . click);
类MyThread实现不可运行{
int click=0;
螺纹t;
私有易失布尔运行=真;
public MyThread(int p){
t=新线程(这个);
t。设置优先级(p);
@覆盖
公共无效运行(){
(跑步时){
点击;
公共无效站点(){
跑步=假;
public void start() {
t。start();
}
该程序的输出结果与中央处理器有关,运行本程序还能看出中央处理器的速度。
2)、睡眠睡眠方法
线程睡眠()是一个静态方法,它强制线程进入睡眠状态。在线程中使用睡眠()方法是非常必要的,它起到使线程停顿的作用睡眠()方法可能抛出中断异常异常,在使用睡眠()方法时一定要进行异常处理。
公共类测试{
public static void main(String[]str){
神话阅读1 t1=新神话阅读1();
神话阅读2 T2=新神话阅读2();
神话阅读3 T3=新神话阅读3();
t1。start();
T2。start();
T3。start();
类流言1扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。打印();
尝试{
线程。睡眠(1000);
} catch(异常e) {
System.err.println(异常: e);
类流言2扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。打印();
尝试{
线程。睡眠(1000);
} catch(异常e) {
System.err.println(异常: e);
类流言3扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。打印();
尝试{
线程。睡眠(1000);
} catch(异常e) {
System.err.println(异常: e);
}
我们可以看到运行结果还是不完全确定的,睡眠()方法也只是让每个线程都有运行的机会。
3)、加入加入方法
加入()方法使一个线程一跟在当前运行的线程2的后面运行,当线程一运行完后再继续运行线程2。我们先来看一个例子:
公共类测试{
public static void main(String[]str){
神话阅读1 t1=新神话阅读1();
神话阅读2 T2=新神话阅读2();
神话阅读3 T3=新神话阅读3();
t2.mt1=t1
t1。start();
T2。start();
T3。start();
类流言1扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。println();
尝试{
线程。睡眠(5000);
} catch(异常e) {
System.err.println(异常: e);
类流言2扩展线程{
公共流言1 mt1
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。println();
尝试{
线程。睡眠(5000);
} catch(异常e) {
System.err.println(异常: e);
if (i==10) {
尝试{
mt1。join();
} catch(异常e) {
System.err.println(异常: e);
类流言3扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。println();
尝试{
线程。睡眠(5000);
} catch(异常e) {
System.err.println(异常: e);
}
我们可以看到运行结果为:
( I=10)成功构建(总时间: 29 秒)
当i=10后,我们看到只打印出三角和实心圆,即线程一种网络的名称(传输率可达1.54mbps)级(一种通讯线路的名称)和t3,当一种网络的名称(传输率可达1.54mbps)级(一种通讯线路的名称)运行结束后,我们看到又打印出了正放心,即t2。
4)、产量让步方法
产量()方法使当前运行的线程回到可运行状态,状态的问题将在第五小节讲到收益率()方法的作用是让有相同优先级的线程获得运行机会收益率()方法通常被称为让步方法,但它往往达不到让步的目的,因为它只是让当前线程回到可运行的状态,很可能运行的线程又会是这一个。下面的例子使用默认优先级讲解产量()方法:
公共类测试{
public static void main(String[]str){
神话阅读1 t1=新神话阅读1();
神话阅读2 T2=新神话阅读2();
神话阅读3 T3=新神话阅读3();
t1。start();
T2。start();
T3。start();
类流言1扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。打印();
Thread.yield().
类流言2扩展线程{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
系统。出去。打印();
Thread.yield()。
类MyThread3扩展Thread{
@覆盖
公共无效运行(){
for(int I=0;i i ) {
system . out . print();
}
我们对t1和t2执行yield()方法,结果会打印出一系列三角形,即t3。但是让步并不完全成功。三角形中仍然有正方形和圆形:
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。