《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 ...
随机推荐
- javascript小实例,实现99乘法表及隔行变色
人生短暂,废话不多说,直奔主题! 这个小实例的要求: 实现在页面中输出99乘法表.(要求:以每三行为一组,实现隔行变色(颜色为白,红,黄(也可自己定义)),鼠标滑过每一行,行背景颜色变为蓝色,鼠标离开 ...
- .NET 单元测试的利剑——模拟框架Moq(简述篇)
.NET 单元测试的利剑--模拟框架Moq 前言 这篇文章是翻译文,因为通过自己参与的项目,越发觉得单元测试的重要性,特别是当跟业务数据打交道的时候的,Moq就如雪中送炭,所以想学习这个框架,就从这篇 ...
- Java高并发--消息队列
Java高并发--消息队列 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 举个例子:在购物商城下单后,希望购买者能收到短信或者邮件通知.有一种做法时在下单逻辑执行后调 ...
- Android view显示在软键盘上方
给EditText外加一个ScrollView,将高度设置统一,并给ScrollView设置属性 android:fillViewport="true". 注:ScrollVie ...
- es6 语法 (let 和const)
一.let 和const 1.let 只在自己声明的块作用域中有效: function test(){ let a = 'a'; var b = 'b'; for(let i =1;i<3;i+ ...
- JS对全角与半角的验证,相互转化以及介绍
1.什么是全角和半角? 全角:是一种电脑字符,是指一个全角字符占用两个标准字符(或两个半角字符)的位置.全角占两个字节. 汉字字符和规定了全角的英文字符及国标GB2312-80中的图形符号和特殊字符都 ...
- 深度学习新星:GAN的基本原理、应用和走向
深度学习新星:GAN的基本原理.应用和走向 (本文转自雷锋网,转载已获取授权,未经允许禁止转载)原文链接:http://www.leiphone.com/news/201701/Kq6FvnjgbKK ...
- Android内存优化(一)Dalvik虚拟机和ART虚拟机对比
1.概述 Android4.4以上开始使用ART虚拟机,在此之前我们一直使用的Dalvik虚拟机,那么为什么Google突然换了Android运行的虚拟机呢?答案只有一个:ART虚拟机更优秀. 2.D ...
- Vue.js 2.x:组件的定义和注册(详细的图文教程)
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 前言 什么是组件 组件: 组件的出现,就是为了拆分Vue实例的代码量的, ...
- ERP承接新后台优惠规则问题
一.后台在哪配置优惠规则? 1.设置优惠时间段: 2.添加优惠活动: 关于自动和手动: 自动:创建后,ERP同步数据后即生效. 点餐,活动会自动生效,自动计算金额. 手动:创建后,ERP需要手 ...