java 多线程简介 优缺点

(一)进程的出现

大家都知道,操作系统出现之前,计算机只能从头到尾执行一个程序,对计算机的资源是一种严重的浪费。最后操作系统出现了,计算机可以并行运行多个任务,每个任务都在自己的进程当中运行,操作系统为每个进城分配硬件(CPU,内存,文件句柄等)资源。那么操作系统解决了什么问题呢,我们总结一下:

  • 资源利用率
  • 公平性
  • 便利性

在这种分时系统中,每个进程,都拥有自己的存储指令,内存空间,并且以串行方式执行指令。串行指令有它自己的好处:直观,简单。正是促进进程出现的因素,也同样促进了线程的出现。

(二)线程的出现

线程允许在同一个进程中同时出现多个程序控制流程。线程会共享进程范围内的资源,例如内存,文件句柄。由于同一个进程中的所有线程都将共享进程的内存地址空间,因此这些线程都能访问相同的变量,并在统一个堆上非配对象,这就需要一种控制数据共享的机制,即我们说的同步!

线程解决了什么问题呢?

  1. 发挥多处理器的强大功能: 现在计算机上多处理器变的十分普及,即使低端服务器上4个处理器8个处理器已经很普遍。因为通过提高时钟频率来提升性能已经变的越来越困难。所以很多芯片 厂商,都加快了向单个芯片上集成处理器的步伐。因为在现代的操作系统上,线程是基本的调度单位,如果一个进程里边只有一个线程,那么假如是一个4个处理器 的计算机,将会有75%的浪费。随着处理器增多这种浪费会越来越严重。

  2. 更简单的多任务建模:通过使用线程可以将复杂并且异步的工作流程进一步分解为一组简单并且同步的工作流。每个工作流在一个单独的线程中运行。在特定的位置进行同步交互。
  3. 异步事件的简化处理:如果我们编写一个服务端接收大量客户端socket请求连接的程序的时候,如果用一个线程并且使用同步IO来处理所有的请求,自编程上面是很简单的,但是如果有耗时的业务逻辑,则会堵塞其他客户端连接。为了解决这种问题,我们可以采用如下两种方法:每个客户端过来,我们可以开启一个worker线程,这样自然不会产生阻塞;采用非阻塞IO,就是我们常说的java NIO(基于操作系统的select或者poll系统调用),这中方法也能解决大量客户端连接,线程阻塞问题,但是NIO编程复杂度很高,需要处理的细节比较多(不过现在成熟的nio框架也比较多,比如netty,mina)。对于第一种方法,大家可能会担心,如果创造太多的线程代价太大,耗费资源太严重,确实在早期的操作系统上对单个进程中可创建的线程数量有一定的限制,差不多几百个。但是现代操作系统上,线程数量已经有了极大的提升,有些已经支持数十万个线程,为每个客户端分配一个线程是有可能的。

 线程带来了什么问题?

  1. 安全性问题:如果同段程序,同步问题处理的不好的话,很可能在单线程环境下可以正常工作,但是在多线程环境下会产生不正确的结果。因为在多线程环境下,竞态条件在未经过合理同步的情况下的执行顺序是不可预测的。因为未经同步的代码块,无论是编译器,硬件还是运行时可能都会对指令进行重排序,或者其他优化,例如对寄存器或者处理器中的变量进行缓存,这些缓存过的变量对于其他线程来说是不可见的(这是硬件或者虚拟机的一种优化手段)。
  2. 活跃性问题: 单线程中的活跃性问题比如死循环。多线程的活跃性问题包括死锁,饥饿,以及活锁。
  3. 性能问题:在一个好的设计当中,多线程可以提高程序的性能。但是在多线程程序中,线程的创建销毁,以及线程之间的互相切换都是会消耗时间的。对共享数据的同步,会抑制编译器对程序的优化等都会增加性能的开销。

 

                    

猜你喜欢

转载自study-a-j8.iteye.com/blog/2361139