线程简介
| 本文总阅读量次线程简介
1. 什么是线程
现代操作系统在运行程序时,会为其创建一个进程。比如你现在用的浏览器,系统就会为其创建一个甚至多个进程。引入进程的目的是为了更好的使操作系统并发执行程序。来提高资源利用率和系统吞吐量,增加并发程度。
线程是现代操作系统调度的基本单元,是运行在进程上下文中的逻辑流,是程序执行流的最小单元,也叫轻量级进程(Light Weight Process),也可以称之为CPU的执行单元。一个程序作为一个进程来运行,程序运行过程中能够创建多个线程,而一个线程在一个时刻只能运行一个处理器核心上。引入线程,则是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。线程不拥有系统资源(代码,数据、堆、共享库、文件),只拥有运行中必不可少的资源(线程ID, 栈,栈指针,程序计数器、通用目的寄存器和条件码)。
线程是调度的抽象。Java中将线程的执行和执行对象抽象开来,JDK包中执行的有Thread类,Executor框架,可执行目标有Runaable,Callable。
1.1 线程的优点
- 多处理器使用: 提高资源利用率和系统吞吐量。
1.2 线程的风险
- 安全风险:对于共享变量的访问、操作容易造成安全风险。
- 活跃度风险:死锁引发活动度失败。
- 性能风险:线程之间频繁调度导致上下文切换导致巨大的系统开销。
2. 线程的状态
- 新建(NEW):用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(READY)。
注意:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常。
运行状态(RUNNABLE):Java线程将操作系统中的就绪和运行两种状态笼统的称作“运行中”。
就绪(READY):处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它称为可运行池而不是可运行队列。因为cpu的调度不一定是按照先进先出的顺序来调度的),等待系统为其分配CPU。等待状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会从等待执行状态进入执行状态,系统挑选的动作称之为“cpu调度”。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。也可以对在运行状态的线程调用yield()方法,它就会让出cpu资源,再次变为就绪状态。
运行(RUNNING):处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
等待状态(WAITING):表示线程进入等待状态,进入该状态表示当前线程需要等待其他线程作出一些特定动作(通知或中断)。
超时等待状态(TIME_WAITING):该状态不同于WAITING,它是可以在指定的时间自行返回的。
阻塞(BLOCKED):javase7 docs关于BLOCKED的描述:Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.翻译:阻塞线程是等待获取同步监视器锁的线程。线程等待获取同步监视器锁进入同步代码块/方法,或者调用Object.wait方法后,被唤醒后等待获取同步监视器锁,重入同步代码块/方法。
死亡(DEAD):当线程的run()方法执行完,或者被强制性地终止,就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。 如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
3. 线程优先级
每个线程执行时都有一个优先级的属性,优先级高的线程可以获得较多的执行机会,而优先级低的线程则获得较少的执行机会。与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的也并非没机会执行。
每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,main线程具有普通优先级。
注:虽然Java提供了10个优先级别,但这些优先级别需要操作系统的支持。不同的操作系统的优先级并不相同,而且也不能很好的和Java的10个优先级别对应。所以我们应该使用MAX_PRIORITY、MIN_PRIORITY和NORM_PRIORITY三个静态常量来设定优先级,这样才能保证程序最好的可移植性。
4. Daemon线程
Daemon线程是一种支持型线程,因为它主要被用做程序中后台调度及支持性工作。
注意:构建Daemon线程时,不能依靠finally块中的内容来确保执行关闭或清理资源的逻辑。
守护线程使用的情况较少,但并非无用,举例来说,JVM的垃圾回收、内存管理等线程都是守护线程。还有就是在做数据库应用时候,使用的数据库连接池,连接池本身也包含着很多后台线程,监控连接个数、超时时间、状态等等。调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。守护线程的用途为:1
2• 守护线程通常用于执行一些后台作业,例如在你的应用程序运行时播放背景音乐,在文字编辑器里做自动语法检查、自动保存等功能。
• Java的垃圾回收也是一个守护线程。守护线的好处就是你不需要关心它的结束问题。例如你在你的应用程序运行的时候希望播放背景音乐,如果将这个播放背景音乐的线程设定为非守护线程,那么在用户请求退出的时候,不仅要退出主线程,还要通知播放背景音乐的线程退出;如果设定为守护线程则不需要了。
1 | /** |
5. 引用
- 本文链接: http://blog.programer.group/concurrency/2017-03-16-thread-brief/
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!