java体系中线程的实现
1.使用内核线程实现
内核线程就是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操作调度器对线程进行调度,并负责将线程的任务映射到各个处理器上,每个内核线程可以视作内核的一个分身,这样操作系统就有能力处理多件事情,支持多线程的内核就叫做多线程内核,程序一般不会其使用内核线程,而是去使用内核线程的一种高级接口:轻量级进程,轻量级进程就是我们通常意义上的线程,由于每个轻量级进程都有一个内核线程支持,因此只有先支持内核线程,才能有轻量级进程(1:1关系),由于内核线程的支持,每个轻量级进程都成为一个独立的调度单元,即使有一个轻量级进程在系统中阻塞了,也不会影响整个进程的工作,但是轻量级进程有局限性:1.由于是基于内核线程实现的,所以线程的各种操作(创建,析构,同步)都需要进行系统调用,而系统调用的代价高,需要在用户态和内核态中来回切换,2.每个轻量级进程都需要一个内核线程的支持,因此轻量级进程要消耗一定的内核资源,因此系统支持的轻量级进程是有数量限制的
2.使用用户线程实现
完全建立在用户空间的线程库上的线程,系统内核不能感知线程的存在,用户线程的建立,同步,销毁和调度完全在用户态中实现,如果程序实现得当,这种线程不需要切换到内核态,操作可以快速和低消耗,可以支持规模更大的线程数量,部分高性能数据库中的多线程就是由用户线程实现的,但是由于不用切换到内核态,所以一些问题得不到内核的帮助,比如阻塞任何处理,多处理器系统中任何将线程映射到其他处理器上,这些问题解决起来异常困难
3.使用用户线程加轻量级进程混合实现
即存在用户线程,又存在轻量级进程,用户线程还是完全建立在用户空间当中,用户线程的创建,切换,析构等操作依然廉价,并可以支持大规模的用户线程并发,而操作系统提供的轻量级进程则作为用户线程和内核之间的桥梁,这样可以使用内核提供的线程调度功能和处理器映射,并且用户线程的1系统调用要通过轻量级进程来完成,大大降低了整个经凑被完全阻塞的风险
java体系中线程的调度
主要有两种调度方式:协同式线程调度,抢占式线程调度
1.协同式线程调度:线程的执行时间由自身控制,线程把工作执行完之后,通知系统切换到另一个线程上,协同式调度最大的好处就是实现简单,而且由于线程要把自己的事情干完才会进行线程切换,切换线程对自己也是可知的,所以不存在线程同步的问题,坏处就是线程执行时间不可控,甚至如果一个线程编写有问题,一直不告诉系统进行线程切换,那么程序就会阻塞
2.抢占式线程调度:每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定,线程执行时间可控,不会有一个线程导致整个进程阻塞问题
“建议给某些线程多分配点时间”就引出了线程优先级的概念,优先级越高的线程越容易被系统选择执行
虽然很多操作系统都有线程的优先级,但是这些优先级不一定可以与java中的线程优先级一一对应!
java体系中线程的状态
java定义了5种线程状态,一个线程在任意一个时间点只能有其中一种状态!
1)新建:创建后尚未启动的线程
2)运行:包括操作系统中的正在运行和就绪两种状态,也就是处于此状态的线程可能正在运行或者等待cpu分配时间
3)等待:
*无限期等待:处于这种状态的线程不会被cpu分配执行时间,他们要等待被其他线程唤醒
*限期等待:处于这种状态的线程也不会被cpu分配执行时间,不过无需等待其他线程唤醒,在一定时间后可以由系统唤醒
4)阻塞:阻塞状态在等待获取一个排他锁
5)结束:已终止线程的线程状态