《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 ...
随机推荐
- C#基础知识总结(四)
摘要 循环结构的总结.跳转语句(break.continue).调试程序 一.循环结构的总结 1.while循环 ; ) { Console.WriteLine(i); i++; } 2.do-whi ...
- Java 中变量初始化、子类和父类构造器调用的顺序
先说结论 变量初始化 -> 父类构造器 -> 子类构造器 贴代码 Animcal.java 父类 public class Animal { private static int inde ...
- Ext中defaults与fieldDefaults
不同点:defaults :直接子组件中的默认配置fieldDefaults: 后代组件中的默认配置 相同点:组件自己的配置中指定的值优先
- cron和crontab命令详解 crontab 每分钟、每小时、每天、每周、每月、每年定时执行 crontab每5分钟执行一次
cron机制 cron可以让系统在指定的时间,去执行某个指定的工作,我们可以使用crontab指令来管理cron机制 crontab参数 -u:这个参数可以让我们去编辑其他 ...
- 微信wx.request
官方 wx.request 代码,Post 没成功过,使用Get 方式成功了. wx.request({ url: 'test.php', //仅为示例,并非真实的接口地址 data: { x: '' ...
- jfinal框架学习过程
刚刚学习jfinal,通过一天左右的时间大体上理解了这个框架的用法,我对他的理解是JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速.代码量少.学习简单.功 ...
- es6 语法 (数组扩展)
{ let arr = Array.of(3, 4, 7, 9, 11); console.log('arr', arr); //[3,4,7,9,11] let empty = Array.of() ...
- Salesforce 自定义标签在代码中的应用
自定义标签简介 Salesforce 中自定义标签(Custom Label)的作用是存储一般性的文本,可以用于 Apex.Visualforce 页面.Lightning 组件等地方,用于显示提示信 ...
- 通过 python ssh库连接并发送命令给设备
import paramiko import time hostname = '192.168.248.156' port = 22 user = 'zhou' passwd = ' paramiko ...
- 调用Android自带浏览器打开网页
转载请注明出处: http://blog.csdn.net/lowprofile_coding/article/details/77928608 在Android中可以调用自带的浏览器,或者指定一个浏 ...