线程是什么(Java中的线程)
在我们开始谈线程之前,不得不提下进程。
无论进程还是线程都是很抽象的概念,有一个关于进程和线程很形象的比喻能帮我们更好的理解。
进程就像个房子,房子是一个包含了特定属性的容器,例如空间大小、卧室数量等。 如果你也这样看的话,那么房子自己不会主动做任何事情,它是被动的对象。 而线程则像是房中的居住者,它是主动的对象——居住者要使用不同的房间、看电视、煮饭、洗澡等等。 房子占据着一块真实的土地,正像进程占据着内存。 而房子的居住者可以自由出入所有的房间,而进程中的线程也是类似的,可以自由访问任何进程占据的内存。
按照教科书上的定义,进程是资源管理的最小单位,线程是程序执行的最小单位。 通过上面的比喻,我们可以更容易的理解进程和线程的关系。 进程只是一个容器对象,它负责占据资源(内存地址、文件I/O),而线程共享进程的资源,作为CPU调度的基本单位可以被独立调度。
线程实现
回到我们的题目:java 线程。 java 作为一个跨平台的语言,自然要提供一个跨平台的线程实现。 线程按类型可以分为内核线程(Kernel-Level Thread)和用户线程(User Thread),分类的标准主要是线程的调度者在核内还是在核外。 早期时,一些操作系统因为没有提供线程的原生实现,所以早在JDK1.2之前,java是基于用户线程来实现的。 用户线程是相对内核线程而言,内核线程自然是由操作系统内核支持的线程,由内核来管理和调度。 后来主流操作系统都支持了线程,因此现在java都采用原生线程来实现了。
既然现在的java线程都采用原生系统线程来实现,那么是否每个java线程就对应一个系统内核线程? 对sun jdk而言,在Windows和Linux中都是采用的一对一模型,Linux提供一种称为轻量级进程(LWP)的高级抽象来避免应用直接使用内核线程。 而在像Solaris这样的系统中则不一定了,因为它支持多对多模型。 不过对于底层系统的线程模型到底如何,对java线程而言都是被屏蔽了的,jvm层面提供了一个统一的抽象线程模型。 下图展示了在Linux上java线程实现的模型图
线程数量
曾经碰到一个问题,java程序运行中抛出一个OOM错误如下:
java.lang.OutOfMemoryError: unable to create new native thread
这个问题的原因可能有两种,一种是内存真的不足了,自然无法再创建线程。 另外一种其实是来自操作系统的限制,比如在Linux中,java线程会映射为轻量级进程,那么创建线程的数量自然会受到系统进程数量等资源约束的限制。
对于一个java进程到底能创建多少线程呢,一般我们按经验线程都是在几十到几百之间,顶多1、2k了。 这是为什么呢?java有个启动参数-Xss1m表明每个线程栈大小为1m,那么对内存一般2G的话,总线程数达到2k感觉上都是不可能的。 但实际上做个实验在循环中不断创建新线程,可以不断创建多达几万的线程,这又是为什么? 原因是新创建的线程其实仅仅分配了内存地址空间,但并没有实际去占用那1m的栈空间,栈空间是在线程使用时才去实际占用的。 所以经验是对的,一般对2G的堆内存空间线程数量根据应用类型在几十到几百之间是合适的。
线程状态
java定义了6种线程状态,任一时刻一个线程处于其中一种状态,其状态转换关系如下图:
1. NEW
新创建未启动的线程处于该状态
2. RUNNABLE
调用了start()方法后,线程进入RUNNABLE状态
3. WAITING
不设置timeout的Object.wati()、Thread.join()等方法会让线程进入无限等待,需要等待其他线程显式的唤醒。
4. TIMED_WAITING
Thead.sleep()或设置了timeout的Object.wati()、Thread.join()等方法让线程进入限期等待。
5. BLOCKED
阻塞状态,线程在等待进入同步区域。
6. TERMINATED
线程执行结束,终止状态。
从上面的状态图可以看出,线程从新建、执行到结束是单向的,期间可能会经历等待和阻塞状态,线程执行结束进入终止状态后将不能再重复使用。 任何时候一个CPU核只能执行一个线程,也就是说同时并行运行的线程数与CPU核数相等。 在操作系统内核层面,线程只有分配了CPU的执行时间片,才算处于RUNNING状态。 而当有大于CPU核数的线程需要执行,没有分配到CPU执行时间片的线程则处于READY状态。 RUNNING和READY都是线程在内核的状态,同时映射到java的RUNNABLE状态。 RUNNABLE正如其名,表示可运行的状态,并非正在运行的状态。
线程池
java编程不可避免的要使用线程,而使用线程更常见的方式是使用线程池。 说起池这个东西,我们应该比较熟悉,例如:连接池。 其实池就是一个容器,里面有一堆预先创建好的对象,我们就称其为对象池,而当这个对象具体为线程,那就是线程池了。 前面讲线程状态说过,线程执行从run()方法退出就会进入终止状态,那么这个线程就消亡了,不能再复用。 线程池的概念就是要复用线程,避免创建开销,那么如何复用呢,其实就是要让池中的线程不用从run()方法中退出。 所以为了复用线程,池的实现会与一个阻塞队列结合,空闲时线程阻塞在队列上等待任务到来,任务执行结束后再重新阻塞,永远不会退出。
jdk1.5引入了java.util.concurrent并发包后,我们可以很方便的通过ThreadPoolExecutor来创建线程池
public ThreadPoolExecutor
(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
教师体检有哪些项目(教师资格证体检有不过的吗)央广网北京11月14日消息(总台央广记者韩雪莹)今天(11月14日)是联合国糖尿病日。据统计,我国成年人糖尿病患病率为12。8,患者人数约1。3亿。国家卫生健康委制定的健康中国行动
胃检查要多久(胃吹气检查要空腹吗)胃部不适,在生活中很多人经常出现,而大多数人在出现胃部不适的时候首先会想到进行胃镜检查胃镜检查是目前比较常见的一项检查,它能够帮助检查出胃部不适的主要原因。不过虽说胃镜检查很多人知
公务员体检多少钱(公务员入职体检多少钱)体检费用不能线上报销追踪公务员体检费用恢复医保实时结算泉州网12月3日讯(记者魏晓芳)之前,泉州晚报报道泉州市切换上线国家医疗保障信息平台,导致机关事业单位工作人员健康体检费用需要
员工关系紧张谷歌的人力资源主管辞职谷歌(GoogleLLC)人力资源主管艾琳?纳顿(EileenNaughton)将在员工与管理层关系日益紧张的情况下,辞去该公司的职务。自2006年起,诺顿一直在谷歌工作,并在过去
教大家打印机提示不能打印多份怎么处理近日有关于教大家打印机提示不能打印多份怎么处理的问题受到了很多网友们的关注,大多数网友都想要知道教大家打印机提示不能打印多份怎么处理的具体情况,那么关于到教大家打印机提示不能打印多
欧象地板怎么样(欧象地板是几线品牌)现在随着经济的发展,很多装修业主在装修地面时地板是首要选择,市面上的地板种类繁多,有复合地板,多层地板和强力复合地板等。强力复合地板的使用寿命很长,有些用户善于保养维护地板,即使使
自热地板怎么样(智能发热地板好不好)发热地板给南方人带来方便,没暖气也可过冬冬天是一个寒冷的季节,从燕子南飞,动物冬眠,都可以体会冬季的寒意。在这样的季节,北方人羡慕南方温暖,而南方的人却羡慕北方人可以在地暖上边吃冰
林内燃气热水器怎么样(林内和万和燃气热水器哪个好)或许是对于产品功能的夸大式宣传心存疑虑或心虚,或许是公司还留存一丝工匠精神信仰,在林内官网上并未看到关于MicroBubble燃气热水器新品微纳活氧黑科技和健康美白功能的卖点展示和
为什么不能在床上打坐(打坐排湿气的最好方法)免费学中医活动开启,转发本篇文章到朋友圈或者今日头条,私信作者头条领课,可免费获得600余分钟高清视频,20余种珍藏实战技巧我前几天收到一位粉丝朋友的私信,说他最近总是觉得手脚冰凉
人民币贬值怎么办(人民币昨天突然暴跌)2020年疫情以来,全球各国央行满负荷启动印钞机应对疫情,大水漫灌之后,加速了物价上涨以及货币贬值。今年3月17日18日19日,巴西土耳其俄罗斯央行相继提高基准利率以应对通货膨胀压
为什么不要做外包员工(外包工可以随时辞职吗)年年岁岁花相似,岁岁年年人不同。六月已过,七月流火。一大波刚走出校园的小萌新们,怀揣梦想,憧憬未来,希望在广阔天地,大展身手,有所作为。在此,我想对涉世未深的小可爱们分享一些自己的