Java--五态模型&控制线程

上一篇----线程的创建和启动

五态模型:在线程的生命周期中,有五种状态,分别是新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。

新建和就绪态:

当程序使用new关键字创建一个线程后,该线程就处于新建状态;当调用start()方法后,该线程就处于就绪态。

启用线程使用start()方法,不能使用run()方法!如果直接调用run()方法,系统把线程对象当作普通对象,run()方法当作普通方法而不是线程执行体。

只能对处于就绪态的线程调用start()方法,否则将引发IllegalThreadStateException异常。

如果希望调用子程序的start()方法后子线程立即执行,可以使用Thread.sleep(1)让当前运行的线程睡眠1毫秒。因为这一毫秒CPU不会空闲,它会去执行另一个就绪的线程。

运行态和阻塞态:

处于就绪态的线程获得CPU进入运行态。但一个线程一般不会一直处于运行态,当发生下面的情况时,线程将进入阻塞态:

· 线程调用sleep()方法主动放弃所占用的处理器资源。

· 线程调用一个阻塞式IO方法,在该方法返回前该线程被阻塞。

· 线程试图获得一个同步监视器,但该监视器正被其他线程所持有。

· 线程在等待某个通知(notify)。

· 程序调用了线程的suspend()方法将线程挂起。但这个方法容易导致死锁,不建议使用。

针对上面的几种情况,当发生一下情况时线程会解除阻塞态重新进入就绪态:

· 调用sleep()方法经过了指定时间。

· 线程调用的阻塞式IO已经返回。

· 线程成功地获取了试图取得的同步监视器。

· 线程正在等待某个通知时,其他线程发出了通知。

· 处于挂起的线程被调用了resume()恢复方法。

注意:线程从阻塞态只能进入就绪态,不能直接进入运行态。调用yield()方法可以让运行态的线程进入就绪态。

线程死亡:

线程会以下面三种方式结束,进入死亡状态:

· run()或call()方法执行完成,线程正常结束。

· 线程抛出一个未捕获的Exception或Error。

· 直接调用stop()方法结束线程----该方法容易导致死锁,不建议使用。

注意:

当主线程死亡时,其他线程不受影响,并不会随之结束。一旦子线程启动后,它就和主线程有着相同的地位,不受主线程影响。

可以用isAlive()方法测试一个线程是否死亡。当线程处于就绪、运行、阻塞时返回true,处于新建、死亡时,返回false。

不要对处于死亡状态的线程调用start()方法,对新建状态的线程调用两次start()方法也是错误的。都会引发IllegalThreadStateException异常。

控制线程:

join线程:

Thread提供了一个让一个线程等待另一个线程完成的方法----join()方法。当某个程序执行流中调用其他线程的join()方法时,调用线程就会阻塞,直到被join线程执行完毕为止。

join()方法有以下三种重载形式:

1. join():等待被join线程执行完成。

2. join(long millis):等待被join线程的时间最长为millis毫秒,超出时间则不再等待。

3. join(long millis, int nanos):等待被join线程最长为millis毫秒加nanos毫微秒。一般不使用该形式,一则程序对时间的精度无需精确到毫微秒;二则计算机硬件、操作系统无法精确到毫微秒。

后台线程:

这种线程在后台运行,为其他线程提供服务。也叫“守护线程”、“精灵线程”。JVM的垃圾回收线程就是典型的后台线程。

后台线程有个特征:如果所有前台线程死亡,后台线程会自动死亡。

调用Thread对象的setDaemon(true)方法可以将线程指定为后台线程,注意,该设置必须在线程启动之前设置,也就是说setDaemon(true)必须在start()方法之前调用,否则会引发IllegalThreadStateException异常。判断一个线程是否为后台线程用Thread类的isDaemon()。

前台线程创建的子线程默认是前台线程,后台线程创建的子线程默认是后台线程。

线程睡眠:sleep

如果需要让当前正在执行的线程暂停一段时间并进入阻塞状态,可以调用Thread对象的sleep()方法来实现。sleep()方法有两种重载方式。

· static void sleep(long millis): 让当前正在执行的线程暂停millis毫秒并进入阻塞状态。

· static void sleep(long millis,int nanos): 让当前正在执行的线程暂停millis毫秒加nanos毫微秒并进入阻塞状态。同样的原因不建议使用第二种形式。

当一个线程调用sleep()进入阻塞状态后,在其睡眠时间内不会获得执行机会,即使当前系统中没有其他可执行线程。因此sleep()常用来暂停程序的执行。

线程让步:yield

yield()和sleep()有点类似,它也可以让当前正在执行的线程暂停,但它不会阻塞线程,只是将该线程转入就绪态。yield()只是让线程暂停一下,让系统重新调度一下。完全有可能一个线程调用yield()后又立即被调度出来执行。

sleep()和yield()的区别:

· sleep()方法暂停当前线程后会给其他线程机会,不理会其他线程的优先级;yield()只会给优先级相同或更高的线程机会。

· sleep()方法会将线程转入阻塞态,而yield()方法不会阻塞线程。

· sleep()方法声明抛出了InterruptedException异常,所以调用sleep()方法要么捕捉异常要么显式声明抛出异常;而yield()方法没有声明抛出任何异常。

· sleep()方法比yield()方法有更好的移植性,通常不建议使用yield()方法控制并发线程的执行。

改变线程优先级:

每个线程默认的优先级都和它的父线程相同。一般情况下main()具有一般优先级,由它创建的子线程也具有一般优先级。

Thread类提供了setPriority(int newPriority)、getPriority()方法来设置和获取优先级。setPriority()方法参数是一个1~10的整数,也可以使用Thread类的三个静态常量:

· MAX_PRIORITY: 其值为10;

· MIN_PRIORITY: 其值为1;

· NORM_PRIORITY: 其值为5;

因为有些操作系统不支持10个这么多的优先级,所以为了程序的兼容性最好使用三个静态常量。

下一篇--线程同步&线程通信

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术分享圈

杨老师课堂之JavaEE三大框架Struts2入门第一课

...

7330
来自专栏Java帮帮-微信公众号-技术文章全总结

Java多线程详解1

Java多线程详解 ? ? ? ? Java线程:概念与原理 一、操作系统中线程和进程的概念 现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。 进...

47190
来自专栏代码世界

23种设计模式之单例模式

单例模式    单例模式(Singleton Pattern)是一个比较简单的模式,其定义为:Ensure a class has only one insta...

348140
来自专栏24K纯开源

使用Qt installer framework制作安装包

一、介绍     使用Qt库开发的应用程序,一般有两种发布方式: (1)静态编译发布。这种方式使得程序在编译的时候会将Qt核心库全部编译到一个可执行文件中。其优...

34280
来自专栏月牙寂

k8s源码分析------第三方库etcd client分析

第一时间获取文章,可以关注本人公众号 月牙寂道长 yueyajidaozhang

40460
来自专栏陈树义

1.Redis 的安装

一、Redis 介绍 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。...

30590
来自专栏coder修行路

Python爬虫番外篇之Cookie和Session

关于cookie和session估计很多程序员面试的时候都会被问到,这两个概念在写web以及爬虫中都会涉及,并且两者可能很多人直接回答也不好说的特别清楚,所以整...

24570
来自专栏北京马哥教育

一周文章推送:

文章名称:nginx + php-fpm fastcgi防止跨站、跨目录的安全设置 我们知道apache php mod的方式可以很方便的配置 open_bas...

30670
来自专栏java一日一条

Java Socket 编程原理及教程

对于Java Socket编程而言,有两个概念,一个是ServerSocket,一个是Socket。服务端和客户端之间通过Socket建立连接,之后它们就可以进...

11310
来自专栏xingoo, 一个梦想做发明家的程序员

【web必知必会】——图解HTTP(上)

  本篇总结关于http的相关知识,主要内容参考如下导图: ?   主要讲解的内容有:   1 URL与URI的区别。   2 请求报文与相应报文的内容。   ...

21390

扫码关注云+社区

领取腾讯云代金券