一、线程的优势

(1)充分发挥多处理器的强大能力:由于线程是CPU调度和分配的基本单位,因此如果在程序中只有一个线程,那么最多同时在一个处理器上运行。在双核处理器系统上,单线程的程序只能使用一半的CPU资源,而在拥有100个处理器的系统上,将有99%的资源无法使用。另一方面,多线程程序可以同时在多个处理器上运行。如果设计合理,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率。
使用多个线程 还有助于在单处理器系统上获取更高的吞吐率,如果程序是单线程的,那么当线程等待某个同步IO操作完成时,处理器将处于空闲状态。而在多线程程序中,如果一个线程在等待IO才做完成时,另一个线程可以继续运行,使程序能够在IO阻塞期间继续运行。

(2)建模的简单性:当只需要执行一种类型(例如修改12个错误)的任务时,在时间管理方面比执行多种类型(修复错误、修改幻灯片等)的任务要简单。当只有一种类型的任务需要完成时,只需做这一件,直到所有的任务完成,不需要进行切换。

(3)异步事件的简化处理:服务器应用程序在接受来自多个远程客户端的套接字连接请求时,如果为每个连接都分配其各自的线程并且使用同步IO,那么将会大大降低开发难度。

(4)响应更灵敏的用户界面:在现代的GUI框架中,例如AWT和Swing等工具中,都采用一个事件分发线程(Event Dispatch Thread,EDT)来替代主事件循环。当某个用户界面事件发生时,在事件线程中将调用应用程序的事件处理器。由于大多数GUI框架都是单线程子系统,因此到目前为止仍然存在主事件循环,但它现在处于GUI工具的控制下并在自己的线程中运行,而不是在应用程序的控制下。

二、线程带来的风险

(1)安全性问题:线程安全性可能是非常安全的,在没有充足同步的情况下,多个线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果,下面的UnsafeSequence类中将产生一个整数值序列,该序列中的每个值都是唯一的,在这个类中简要地说明了多个线程之间的交替操作将会如何导致不可预料的结果。在单线程环境中,这个类能正确的工作,但在多线程环境中则不能。

package MultiThreading;

/**
 * Created by L_kanglin on 2017/4/11.
 */
public class UnsafeSequence {
    private int value;
    //返回一个唯一的数值
    public int getNext(){
        return value++;
    }
}

UnsafeSequence的问题在于,如果执行时机不对,那么两个线程在调用getNext时会得到相同的值。虽然递增运算someVarible++看上去是单个操作,但事实上它包含三个独立的操作:读取value、将value加1、并将计算结果写入value。由于运行时可能将多个线程之间的操作交替执行,因此这两个线程可能同时执行读操作,从而使它们得到相同的值,并都将这个值加1,结果就是,在不同的线程的调用中返回了相同的数值。

(2)活跃性问题
安全性的含义是“永远不发生糟糕的事情”,而活跃性则关注于另一个目标,即“某件正确的事情最终会发生”。比如:如果线程A在等待线程B释放其持有的资源,而线程B永远都不会释放该资源,那么A将一直等待下去。

(3)性能问题
在多线程程序中,当线程调度器临时挂起活跃线程并转而运行另一个线程时,就会出现频繁的出现上下文切换操作,这种操作将带来极大的开销:保存和恢复执行上下文,丢失局部性,并且CPU时间将更多的花在线程调度而不是线程运行上。