《Java大学教程》—第22章 多线程程序
22.2 进程(process):P551
时间切片(time-slicing):处理器只是完成了一个任务的一部分工作,然后完成下一个任务的一部分工作,
因为处理吕每次完成工作的时间都非常短,因此看起来这些任务是同时完成的。
进程:一个运行的程序通常称为一个进程。
并发进程(concurrent process):两个或多个可以同时执行的进程称为并发进程。
在多个进程并发执行时,每个进程都有自己的存放程序代码和数据的存储空间,并且每个进程的存储空间对于其他进程都是受保护的,所有这些工作都由操作系统完成。
22.3 线程(thread):P552
线程:一个程序执行的多个独立任务称为线程。通常将线程称为轻量级进程(lightweight process),因为也管理进程相比,管理线程需要占用较少的系统资源。
线程没有完全独立的存储空间,线程之间共享代码区和存储区。
管理线程的方式也是基于时间切片原则,由JVM和OS协同管理。
22.4 Thread类
继承Thread类实现线程。控制线程用三个方法:start(), run(), finish()
主要执行代码在run()方法中。
注:run()方法结束后,这个线程就运行结束了,不可以再次调用,必须重新创建。原因也可参考图22-2的状态转换图,线程进入TERMINATE状态中,无法再次启动。
22.5 线程的执行与调度
份额(quantum):每个进程或者线程都可以获得处理器上的一小段时间--称为份额,然后轮转到下一个进程或线程。
份额内时间没有用完时,也可以使用sleep()方法,强制放弃CPU的占用权,将CPU还给OS,从而可以继续分配给下一个进程或线程。
注:sleep()方法传入的时间间隔(以毫秒为单位),可能会抛出InterruptedException异常,必须写在try...catch代码块中。
22.6 Runnable接口
创建一个实现Runnable接口的类,然后将类的实例作为Runnable接口的参数传入Thread对象的构造函数中。
后面的工作主要就是操作Thread的对象,与前面扩展Thread类的方法一样了。
注:此处的Thread对象是独立创建的,前面是对Thread类的继承。
22.7 线程同步:P562
异步行为(asynchronous behaviour):
在一般情况下两个或多个并发执行线程的行为并不是协同的,而且无法预知在某个时间段内哪个线程将会占用CPU,这种非协同的行为称为异步行为。
互斥访问(mutual exclusion):需要将访问缓冲区的程序段看作临界区(critical section)--即在任何时刻只能被一个进程访问的区域,实现临界区的方式称为互斥访问。
忙等待(busy waiting):被某个线程执行的方法循环中反复执行,直到满足某个条件才能终止。效率太低,可以使用wait()方法将线程挂起,直到被其他线程的消息唤醒。
在Java中创建一个monitor对象(监视器),monitor类的所有方法在任何时刻都只能被一个线程访问。
可以在方法的头部使用synchronized修饰符,由于方法被同步(synchronized),所以一旦有某个对象调用该方法,那么该方法将被置上一个锁(lock),
其他对象必须在该方法执行完成后才能访问它。
注1:为什么要加锁?是因为你有临界区,对这个临界区加锁才是目的。
因此锁的目的:当前类(即this.静态变量),当前对象(即this.变量),当前对象中创建的对象(即this.对象变量),外部传入到当前对象中的对象。
注2:什么可以加锁?对象,只有对象可以加锁。
在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问。
JVM会记录并且监管这个锁,当线程获取锁后计数器由0变1,线程若访问同样锁的其他方法,计数器还会继续增加,从而保证线程完全释放这个锁后才会允许其他线程访问。
所以基本数据类型的变量是不能作为临界区的,也就不能被加锁。
注3:怎么样加锁?使用synchronized对静态方法、方法、对象变量加锁。
static synchronized aStaticMethod(){...} // “当前类(即this.静态变量)”加锁
synchronized aMethod(){...} // “当前对象(即this.变量)”加锁
synchronized (aObjectVariable){...} // “当前对象中创建的对象(即this.对象变量)”或“外部传入到当前对象中的对象”加锁。
22.8 线程状态:P563
状态转换图:图22-2 一个线程的状态转换图
start()启动一个线程-->线程进入ready(就绪)状态。
dispatch()调度一个线程-->线程进入running(运行)状态。
线程运行时间超时、yield()强制一个线程放弃CPU-->线程进入ready(就绪)状态。
sleep()睡眠一个线程-->线程进入sleeping(睡眠)状态-->睡眠时间超时-->线程进入ready(就绪)状态。
wait()-->线程进入waiting(等待)状态-->获得其他线程notify()或notifyAll()方法通知-->线程进入ready(就绪)状态。
由于等待输入或等待外部设备可用-->线程处于blocked(阻塞)状态-->阻塞时间超时或设备正常-->线程进入ready(就绪)状态。
run()方法完成后,线程被终止。
22.10 Timer类:调度线程
在固定时间间隔内生成ActionEvents对象。因此,必须将一个Timer对象关联到一个ActionListener对象。
只要Timer对象生成一个ActionEvent对象,都会执行与Timer对象相关的ActionListener对象的actionPerformed()方法。
自测题:
1. 如何通过时间切片实现并发:P552
时间切片(time-slicing):处理器只是完成了一个任务的一部分工作,然后完成下一个任务的一部分工作,
因为处理吕每次完成工作的时间都非常短,因此看起来这些任务是并发完成的。
2. 进程与线程的区别:P552
每个进程都有完全独立的存储空间,用于存放程序的代码和数据,并且每个进程的存储空间对于其他进程都是受保护的,所有这些工作都由操作系统完成。
每个线程没有完全独立的存储空间,线程之间共享程序的代码和数据,线程的调度由JVM和操作系统协同完成。
3. 异步线程执行和同步线程执行的区别:P562
异步执行线程:无法预知某个时间段内哪个线程将会占用CPU,也无法估计程序执行的结果。
同步执行线程:确保线程对于临界区是互斥访问的,当某个线程执行同步代码时,其他线程无法再调用同步代码,必须等待前面执行的进程解锁。
4. 临界区和互斥的概念:P562
访问缓冲区的程序段看作临界区(critical section)--即在任何时刻只能被一个进程访问的区域。
实现临界区的方式称为互斥访问(mutual exclusion)。
Jav提供了在多线程程序中实现互斥的机制,即每个对象都有一个monitor(监视器),monitor类的所有方法在任何时刻都只能被一个线程访问。
只需要在方法的头部使用synchronized修饰符,由于方法被同步,所以一旦有某个对象调用该方法,那么这个方法就会被上锁,其他对象如果同时想访问就必须等待。
5. 如何在Java程序中避免忙等待:P562
使用wait()方法将线程的执行挂起,直到它收到另一个进程的消息将它唤醒。就可以避免出现忙等待。
6. Threads6.java RunThreads6.java
编程练习:代码附件
3. CounterVersionFour.java RunCounterVersion.java CounterThread.java
《Java大学教程》—第22章 多线程程序的更多相关文章
- 正在学习的Java大学教程
推荐本书<Java大学教程> 看的人比较少,我也是多年不看书了,基于教程一般选国外的方法,从图书馆选了本书. 看了一半,感觉书的内容比较认真,对于基本的Java知识都算介绍全了,而且全书是 ...
- 《Java基础教程》第一章学习笔记
Java 是什么呀! 计算机语言总的来说分成机器语言,汇编语言,高级语言.其中Java一种高级计算机语言,它是一种可以编写跨平台应用软件,完全面向对象的程序设计语言. Java划分为三个技术平台,Ja ...
- 《Java大学教程》—第13章 程序包
接下来,是第二学期的内容,也是相对深入的Java学习. 自测题:1. 在类的开发过程中,程序包的作用是什么?P321程序包是为了方便定位和部署类,还可以避免将来类之间出现名称冲突. 2. ...
- 《Java大学教程》—第24章 Java的背景
本章主要介绍的是Java的背景知识,通过了解历史知道Java与其他语言的区别,以便更好选择在什么场景下使用Java. 24.2 语言的尺寸Java语言短小.紧凑,以C++为基础,放弃了一些特定的 ...
- 《Java大学教程》—第23章 Java网络编程
本章主要关注的是Java的几个应用网络编程的场景,对于网络编程没有太多深入介绍,而Java本来也没有多少针对网络编程的特性.虽然Java有个Applet的概念,但是真用这个的开发的场景其实不多. 23 ...
- 《Java大学教程》—第19章 改进用户界面
用户与程序交互的媒介称为用户界面(user interface)或人机界面(human-computer interface). 19.2 Border接口8个实现Border接口的标准边框类: ...
- 《Java大学教程》—第14章 抽象、继承和接口
自测题:1. 解释抽象和抽象数据类型的概念.P333抽象的概念是仅仅关注对象可以完成什么工作,而不必担心如何完成工作的细节.类模板通常被称为抽象数据类型.因为这类数据暴露给用户的所有信息仅仅是方 ...
- 《Java大学教程》—第11章 案例研究--第1部分
自测题:1. 图11-1的UML设计中各个类之间的关系.Hostel与TenantList是关联关系:TenantList和PaymentList与ObjectList是泛化关系.TenantL ...
- 《Java大学教程》—第20章 文件处理
记录():一个单独的数据实例.域():一个属性. 20.3 输入和输出设备:P484输入过程和输出过程.操作系统负责建立三个流(stream):标准输入流(System.in).标准输出流(Sy ...
随机推荐
- 隐藏马尔科夫模型HMM
概率图模型 HMM 先从一个具体的例子入手,看看我们要解决的实际问题.例子引自wiki.https://en.wikipedia.org/wiki/Hidden_Markov_model Consid ...
- [转]Ble蓝牙的使用手册
本文转自:https://blog.csdn.net/dodan/article/details/52060446 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.cs ...
- 第一册:lesson thirteen.
原文:A new dress. A:What color's your new dress? B:It' green.Come upstairs and see it. A:Thank you. B: ...
- 【转载】C#递归删除文件夹目录及文件
在C#文件操作过程中,有时候需要删除相应目录,如果文件夹中含有其他文件夹或者文件,也需要一并进行删除,此时可能就需要使用递归来删除文件夹目录以及文件,递归过程中,如果遍历的对象是文件夹,则删除文件夹, ...
- 腾讯云图片鉴黄集成到C#
官方文档:https://cloud.tencent.com/document/product/641/12422 请求官方API及签名的生成代码如下: var urlList = new List& ...
- [android] 在不同的activity之间传递数据
新建一个activity,继承Activity 清单文件中进行配置,添加<activity/>节点 设置名称 android:name=”.类名” 点 代表的是当前包名,也可以不写 新建一 ...
- 详解MySQL基准测试和sysbench工具(转)
前言 作为一名后台开发,对数据库进行基准测试,以掌握数据库的性能情况是非常必要的.本文介绍了MySQL基准测试的基本概念,以及使用sysbench对MySQL进行基准测试的详细方法. 文章有疏漏之处, ...
- C# 从Excel中读取条码
条形码的应用三------从Excel文件中读取条形码 介绍 上一篇文章,我向大家展示了生成多个条形码并存储到Excel文件中的一个方法.后来我又有了个想法:既然条码插入到excel中了,我可不可以从 ...
- JVM 垃圾回收机制
首先JVM的内存结构包括五大区域: 程序计数器.虚拟机栈.本地方法栈.方法区.堆区.其中程序计数器.虚拟机栈和本地方法栈3个区域随线程启动与销毁, 因此这几个区域的内存分配和回收都具有确定性,不需要过 ...
- Springboot整合Websocket遇到的坑
Springboot整合Websocket遇到的坑 一.使用Springboot内嵌的tomcat启动websocket 1.添加ServerEndpointExporter配置bean @Confi ...