线程

1 进程

资源分配和管理的最小单元。

2 线程

CPU调度的最小单元。
线程允许在同一个进程中同时存在多个程序控制流。

2.1 优势

2.1.1 发挥多处理器的功能

多线程程序可以同时在多个处理器上并行执行。

2.1.2 提高处理器吞吐

多线程还有助于在单处理器系统上获得更高的吞吐。
当线程发生IO阻塞时,系统将CPU资源切换到其他可运行的线程。

2.1.3 方便建模

使用线程,可以将复杂并且异步的工作流进一步分解为一组简单的并且同步的工作流,每一个工作流在一个单独的线程中执行。

2.1.4 简化异步事件的处理

异步IO复杂性较高,很难编写安全程序。
如果每个请求都有自己的处理线程,那么在处理某个请求时发生阻塞将不会影响其他请求的处理。

2.1.5 更灵敏的图形界面

将运行时间较长的任务放在一个独立的线程中执行,那么事件线程就能及时的处理用户界面的事件。

2.2 风险

2.2.1 安全问题(数据安全问题)

由于多个线程共享相同的内存地址空间,并且是并行运行,因此他们可能访问或修改其他线程正在使用的变量。
要想多线程程序的行为可以预测,必须对共享变量的访问操作进行协同,这样才不会在线程间发生彼此干扰。

2.2.2 活跃性问题

当某个操作无法继续执行下去时,便发生了活跃性问题。
单线程情况下,活跃性问题就是无意中造成了死循环,导致之后代码无法运行。
多线程情况下,由于包含数据各种手段的存在容易造成死锁、饥饿、活锁等活跃性问题。

2.2.3 性能问题

多线程的引入会导致一些开销:

  1. 上下文切换开销
  2. 同步机制导致各类优化手段的失效(编译器优化、内存缓存优化、CPU指令优化等)同时增加共享内存总线的数据同步开销

2.3 线程无处不在

每个java进程都在使用多线程。
框架通过框架线程调用应用程序代码将并发性引入到程序中。

2.3.1 Timer

TimerTask将在Timer管理的线程中执行,而不是由应用程序管理。

2.3.2 Servlet&JSP

当一个servlet访问在多个servlet或者请求中共享的对象时,必须正确的协同对这些对象的访问,因为多个请求可能在不同的线程中同时访问这些对象。

2.3.3 RMI

正确协同在过个对象中共享的状态,以及对远程对象本身状态的访问。

2.3.4 Swing&AWT

他们创建一个独立的事件线程来处理用户出发的事件,并对图形界面进行更新。

2.4 线程状态

2.4.1 new

new Thread之后,线程未执行前状态

2.4.2 runnable

可运行状态:

  1. new状态的线程调用start方法
  2. 调用Thread.yield让出CPU资源
  3. running状态线程耗尽所分配CPU时间片
  4. join等待线程已完成
  5. sleep()超时
  6. wait资源调用notify或notifyAll或超时
  7. block线程获取锁
2.4.3 running

runnable状态的线程获取CPU资源后真正执行

2.4.4 waiting

等待状态,调用wait、join等方法

2.4.5 timed_waiting

超时等待,调用sleep(timeout)、wait(timeout)、join(timeout)

2.4.6 block

进入同步方法同步块前,等待获取锁对象

2.4.7 dead

线程死亡

  1. 线程成功执行完成
  2. 抛出未捕获异常
wenxinzizhu wechat
扫一扫,添加我的微信,一起交流共同成长(备注为技术学习)