
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
线程是程序员在学习Java编程开发的时候需要重点掌握的一个编程知识点,而本文我们就简单来学习一下,Java编程线程的实现与状态分析。
一、线程
线程是Java里进行CPU资源调度的小单位。JavaThread类的关键方法都是native方法,意味着Java线程是与操作系统平台相关的。
二、线程的实现
Java线程如何实现并不受Java虚拟机规范的约束,虚拟机厂商自行决定。目前主流的Java虚拟机的线程模型都是基于操作系统原生线程模型来实现的,Java线程与操作系统的内核线程是1:1的映射关系。JVM不会干涉线程的调度和执行,全权交给操作系统去处理。
Java线程有6种状态(Thread.State枚举类定义):new,runnable(包含ready和running),blocked,timed_waiting,waiting,terminated。
三、协程
协程(coroutine),是协同式调度的用户线程(非内核线程),分有栈/无栈协程。
协程的出现是因为操作系统内核线程有其天然缺陷:线程切换和调度的成本高昂,即响应中断、保护和恢复执行现场的成本高昂。系统能容纳的线程数量也有限(在几百和上千的量级)。协程的主要优势是轻量,一个协程的栈大小通常在几百字节到几KB(而线程的默认内存大小是1M),系统能容纳几万量级的协程。
纤程(Fiber),是一种有栈协程的特例实现,由JVM调度而非操作系统调度,由OpenJDKLoom项目开发。
四、线程的开销
有以下4种开销:
线程创建。1步newThread()做初始化操作,2步thread.start()调用操作系统API创建nativethread。同时也有对内存的开销,通过-Xss设置线程堆栈内存大小,默认值1M。当线程被使用时才会真正消耗物理内存,否则只分配给虚拟内存。线程创建和启动约70-80微秒。
线程切换。也叫上下文切换,需要保存和恢复执行现场。当一个新线程被切换进来时,它所需要的数据可能不在当前处理器的缓存中,因此线程在次运行时会更缓慢。调度器会为每个线程分配一个小执行时间,以分摊上下文切换的开销,从而提高整体的吞吐量,但缺点是损失了响应性。一次线程切换的耗时约几微秒,切换次数可以通过vmstat命令查看(unix系统)。
内存同步。synchronized和volatile提供的可见性保证中可能会使用内存栅栏(MemoryBarrier),它会刷新缓存,使缓存无效,同时会抑制一些编译器优化操作,使大多数操作不能被指令重排,从而对性能带来间接影响。同步还会增加共享内存总线上的通信量,而所有处理器都将共享这条总线,从而影响其他线程的性能。如果是无竞争的同步,那么它对性能的影响微乎其微,可以忽略它。关注重点应该放在有竞争的同步。
阻塞。当在锁上发生竞争时,竞争失败的线程肯定会阻塞。JVM在实现阻塞时可以采用自旋等待(Spin-waiting)或者通过操作系统挂起线程。如果等待时间短,自旋等待的效率高;反之,则线程挂起的效率高。自旋等待增加了CPU时钟的开销,挂起则增加了两次额外的上下文切换开销。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。