Java与线程

  线程是比进程更轻量级的调度执行单位,线程的引入可以把一个进程的资源分配和执行调度分开,各个线程可以共享进程资源,又可以独立调度。

  每个已经执行start()方法且还未结束的java.lang.Thread类的实例就代表了一个线程。

1.线程的实现(三种):使用内核线程实现、使用用户线程实现、使用用户线程加轻量级进程混合实现

  1)使用内核线程实现(一对一线程模型):内核线程就是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操作调度器对线程进行调度,并负责将线程的任务映射到各个处理器上。程序一般不会直接使用内核线程,而是去使用它的一种高级接口——轻量级进程,即线程;只有先支持内核线程,才能有轻量级进程。但轻量级进程具有它的局限性:首先,由于是基于内核线程实现的,所以各种线程操作都需要进行系统调用,而系统调用代价较高,需要在用户态和内核态之间来回切换。轻量级进程要消耗一定的内核资源,因此一个系统支持的轻量级进程的数量是有限的。

  2)使用用户线程实现(一对多线程模型):从广义上,一个线程只要不是内核线程,就可以认为是用户线程。从狭义上,用户线程是指完全建立在用户空间的线程库上,系统内核不能感知线程存在的实现。用户线程的建立、同步、销毁和调度完全在用户台中完成,不需要内核的帮助。使用用户线程的优势在于不需要系统内核支援,所有的线程操作都需要用户程序自己处理。

  3)使用用户线程加轻量级进程混合实现(多对多线程模型):在这种混合实现下,即存在用户线程、也存在轻量级进程。用户线程还是完全建立在用户空间中,因此用户线程的创建、切换等操作依然廉价,并且可以支持大规模的用户线程并发。而操作系统提供支持的轻量级进程则作为用户线程和内核线程之间的桥梁,这样可以使用内核提供的线程调度功能及处理器映射,并且用户线程的系统调用要通过轻量级线程来完成,大大降低了整个进程被完全阻塞的风险。

2.Java线程池调度:指系统为线程分配处理器使用权的过程。主要调度方式分为协同式线程调度和抢占式线程调度

  如果使用协同式调度的多线程系统,线程的执行时间由线程本身控制,线程把自己的工作执行完了之后,要主动通知系统切换到另一个线程上。它最大的好处就是实现简单,而且没有什么线程同步的问题,它的坏处就是线程执行时间不可控制,甚至如果一个线程编写有问题,一直不告知系统进行线程切换,那么程序就会一直阻塞在那里。

  如果使用抢占式调度的多线程系统,那么每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定。在这种实现线程调度的方式下,线程的执行时间是系统可控的,不会有一个线程导致到整个进程阻塞的问题,Java使用道线程调度方式就是抢占式调度。

3.状态切换:Java语言定义了5种线程状态,在任意一个时间点,一个线程只能有且只有其中的一种状态。

  新建(New):创建后尚未启动的线程处于这种状态。

  运行(Runnable):处于此状态的线程有可能正在执行,也有可能正在等待着CPU为它分配执行时间。

  无限期等待(Waiting):处于这种状态的线程不会被分配CPU执行时间,它们要等待被其他线程显式地唤醒。

  限期等待(Timed Waiting):处于这种状态的线程也不会被分配CPU执行时间,不过无需等待被其他线程显式地唤醒,在一定时间之后它们会由系统自动唤醒。

  阻塞(Blocked):线程被阻塞了,阻塞状态和等待状态的区别是:阻塞状态在等待着获取到一个排他锁,而等待状态则是等待一段时间或者唤醒动作的发生。

  结束(Terminated):已终止的线程的线程状态,线程已经结束执行。

posted @ 2019-12-09 13:17  MrHH  阅读(272)  评论(0编辑  收藏  举报