java从诞生开始就明智的选择了内置对多线程的支持,这使得java语言相比同一时期的其他语言具有明显的优势。线程作为操作系统调度的最小单元,多个线程能够同时执行,这将显著提升程序的性能,在多核环境中表现的更加明显。但是,过多的创建线程和对线程的不当管理也容易造成问题。本章将着重介绍java并发编程的基础知识,从启动一个线程到线程间不同的通信方式,最后通过简单的线程池示例以及应用(简单的Web服务器)来串联本章所介绍的内容。
1.线程简介
1.1 什么是线程
现代操作系统中在运行一个程序时,会为其创建一个进程。例如,启动一个java程序,操作系统就会创建一个java进程。现在操作系统调度的最小单元就是线程,也叫轻量级进程(Light Weight Process),在一个进程中可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时进行。
一个java程序从main()方法开始执行,然后按照既定的代码逻辑执行,看似没有其他线程参与,但实际上java程序天生就是多线程程序,因为执行main()方法的是一个名称为main的线程,下面使用JMX来查看一个普通的java程序包含哪些线程
public static void main(String[] args) { //使用java线程管理MXbean ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); //不需要获取同步的monitor和synchronizer信息,进获取线程和线程堆栈信息 ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); for (ThreadInfo threadInfo : threadInfos) { System.out.println("["+threadInfo.getThreadId()+"]"+threadInfo.getThreadName()); } } // [7]JDWP Command Reader // [6]JDWP Event Helper Thread // [5]JDWP Transport Listener: dt_socket // [4]Signal Dispatcher 分发处理发送给jvm信号的线程 // [3]Finalizer 调用对象finalize方法的线程 // [2]Reference Handler 清除reference 的线程 // [1]main main线程,用户程序入口
可以看到,一个java程序的运行不仅仅是面()方法的运行,而是main线程和多个其他线程的同时执行。
1.2 为什么要使用多线程
执行一个简单的“Hello word!”,却启动了那么多“无关”线程,是不是把简单的问题复杂化了?当然不是,因为真确的使用多线程,总能够给开发人员带来显著的好处,而使用多线程的原因主要有以下几点:
1.更多的处理器核心
随着处理器上的核心数量越来越多,以及超线程技术的广泛运用,现在大多数计算机都比以往更加擅长并行计算,而处理器性能的提升方式,也从更高的主频向更多的核心发展。如何利用好处理器上的核心也成了现在的主要问题
线程是大多数操作系统调度的基本单元,一个程序作为一个进程来运行,程序运行过程中能够创建多个线程,而一个线程在一个时刻只能运行在一个处理器核心上。试想一下,一个单线程程序在运行是只能使用一个处理器核心,那么再多的处理器核心加入也无法显著提升该程序的执行效率。相反,如果改程序使用多线程技术,将计算逻辑分配到多个处理器核心上,就会显著减少程序的处理时间,并且随着更多处理器核心的加入而变得更有效率。
2.更快的响应时间
有事我们会编写一些较为复杂的代码(这的复杂代码不是说复杂的算法,而是复杂的业务逻辑)。例如,一笔订单的创建,他包括插入订单数据、生成订单快照、发送邮件通知买家和记录货品销售数量等。用户从单击“订购”按钮开始,就要等待这些操作全部完成才能看到定购成功的结果。但是这么多业务操作,如何能够让其跟快的完成呢?
在上面的场景中,可以使用多线程技术,即将数据一致性不强的操作派发个其他线程处理(也可以使用消息队列),如生成订单快照、发送邮件等这样做的好处就是想用用户请求的线程能够尽可能的处理完成,缩短了响应时间,提升了用户体验。
3.更好的编程模型
java为多线程模型提供了良好、考究并且一致的编程模型,是开发人员能够更加专注于问题的解决,即为所遇到的问题建立合适的模型,而不是绞尽脑汁的考虑如何将其多线程化。一旦开发人员建立好模型,稍做修改总是能够方便的映射到java提供的多线程编程模型上。
1.3 线程优先级
1.4 线程的状态
1.5 Daemon线程
2.启动和终止线程
2.1 构造线程
2.2 启动线程
2.3 理解中断
2.4 过期的suspend()、resume()、stop()
2.5 安全的终止线程
3.线程间通信
3.1 volatile和synchronized关键字
3.2 等待/通知机制
3.3 等待/通知经典案例
3.4 管道输入/输出流
3.5 Thread.jion()
3.6 ThreadLocal的使用
4.线程应用实例
4.1 等待超时模式
4.2 一个简单的数据库连接池示例
4.3 线程技术及其示例
4.4 一个基于线程池技术的简单web服务器
5.本章小结
原文地址:https://www.cnblogs.com/panda777/p/11355589.html