配色: 字号:
第7章 多线程
2015-06-30 | 阅:  转:  |  分享 
  
操作系统支持多进程,使多个程序能并发执行,以改善资源使用率和提高系统效率;操作系统支持多线程进程,能够减少程
序并发时所付出的时空开销,使得并发粒度更细,并发性更好。图7.1多线程进程模型线程是处理器调度和分派的基本单位,也有生
命周期;线程的状态有5种:新建、就绪、运行、等待、终止。线程在其生命周期中经历着状态的变化。publicinterface
Runnable{publicabstractvoidrun();//描述线程操作的线程体}Thread类
具有封装线程对象的能力,并声明创建、管理和控制线程对象的方法。publicvoidrun()
//描述线程操作的线程体publicfinalStringgetN
ame()//返回线程名publicfinalvoidsetName(Stri
ngname)//设置线程名publicstaticintactiveCount()
//返回当前活动线程数publicstaticThreadcurrentThread()//返回当前执
行线程对象publicStingtoString()//返回线程的字符串信息,包括名字、优先级
和线程组publicvoidstart()//启动已创建的线程对象}T
hread类的run()方法声明如下:publicvoidrun()//描述线程操作的线程体{
if(target!=null)target.run();//执行目
标对象的run()方法}(1)线程启动publicstaticvoidsleep(longmillis)
throwsInterruptedExcept
ion//参数millis指定睡眠毫秒数publ
icvoidinterrupt() //设置当前线程对象运行中断标记publicboole
anisInterrupted()//判断线程是否中断1.Thread类中声明了3个表示优先级的公有静态常量:
每个线程对象创建时自动获得默认优先级5,调用setPriority()方法可改变线程对象的优先级,这样,使重要或紧
急的线程拥有较高的优先级,从而能够更快地进入运行态。线程可分为用户线程(userthread)
和守护线程(daemonthread):守护
线程:指在后台运行的线程,也称为后台线程,用于提供后台服务。用户线程:Java创建的线程默认是用户线程
。两者的差别:当进程中还有用户线程在运行时,进程不终止;当进程中只有守护线程在运行时,进程终止。
动画(animation):利用人眼的视觉特性形成的。设有一组连续的图形或图像画面,每次显示其中一幅,停留一点时间就切
换到下一幅,人脑就会产生物体移动或变化的印象。图形动画设计的原理:在画布上绘制一幅图,停留一点时间后,用画布背景色重画
这幅图,就擦掉了原图;错开一些位置重画图形并停留一点时间,再擦除、重画,反复执行,从人的视觉效果来看,就好像图
形在移动。如果两个线程要访问同一资源,则线程间存在资源竞争关系,这就是线程间的间接制约关系。线程互斥:解决线程间
竞争关系的手段。线程互斥:指若干个线程要使用同一共享资源时,任何时刻最多允许一个线程去使用,其他要使用
该资源的线程必须等待,直到占有资源的线程释放该资源。(1)同步语句使用synchronized声明一条语句为临界区,
该语句称为同步语句。同步语句执行过程:(2)同步方法synchronized方法声明当一个进程的多个线程为完成同一
任务而分工协作时,它们彼此之间有联系,知道其他线程的存在,而且受其他线程执行的影响,这些线程间存在协作关系,这
是线程间的直接制约关系。线程同步(synchronization):解决线程间协作关系的手段。线程同步:指两个以上
线程基于某个条件来协调它们的活动。一个线程的执行依赖于另一个协作线程的消息或信号,当一个线程没有得到来自于另一
个线程的消息或信号时则需等待,直到消息或信号到达才被唤醒。(1)背景多个线程需要对同一个共享变量进行
操作,所以多个线程间必须互斥地执行,即这些操作方法必须是互斥的。(3)线程根据信号量状态而执行多个线程间彼此根据信
号量的状态确定该谁执行:当一个线程开始执行时,先要测试信号量的状态,如果状态合适则执行,进行相关操作并更改信号量状态,通知其他
等待线程执行;否则等待,使线程自己处于阻塞状态,直到被唤醒再次执行。publicfinalnativevoidnoti
fy();//唤醒一个等待线程publicfinalnativevoidnotifyAll();//唤醒所有等待
线程实验7线程设计倒计时牌设计图形动画设计7.3.2线程间的竞争关系与线程互斥操作系统提供互斥锁机制:实现并
发线程互斥地进入临界区,对共享资源进行操作。程序员只需要在程序中声明哪个程序段是临界区即可。2.线程互斥和
临界区管理7.3.2线程间的竞争关系与线程互斥3.Java的线程互斥实现Java提供关键字synchron
ized用于声明一段程序为临界区,使线程对临界资源采用互斥使用方式。synchronized的用法:声明一条语句、声明一
个方法;对象:多个线程共同操作的公共变量,即需要被锁定的临界资源;将被互斥地使用;语句:临界区,描述线程对临界资
源的操作。synchronized(对象)语句7.3.2线程间的竞争关系与线程互斥②在此过程中,如果有
第2个线程也希望对同一个对象执行语句,由于作为临界区资源的对象已经被锁定,所以第2个线程必须等待;①当第1个线程希望进入临界区
执行<语句>时,它获得临界资源即指定<对象>的使用权,并将对象加锁(对象锁),然后执行语句对对象进行操作;③当第
1个线程执行完临界区语句,它将释放对象锁;④之后第2个线程才能获得对象的使用权并运行;7.3.2线程间的竞争关系与线程互
斥方法体:临界区;互斥使用(锁定)的是调用该方法的对象。方法声明synchronized(this){方法体
}(3)“同步语句”和“同步方法”比较7.3.2线程间的竞争关系与线程互斥同步语句的作用范围小,只是锁
住部分语句,而不是完整的方法;同步语句指定所要获得锁的对象而不调用方法的对象,这样就增加了灵活性并且缩小了对象锁的作用域。7.
3.2线程间的竞争关系与线程互斥【例7.6】互斥的存/取款线程设计。图7.9带互斥锁的并发线程执行流程7.3.3
线程间的协作关系与线程同步1.线程间的协作关系当合作线程中的一个到达协调点后,在尚未得到其伙伴线程发来的信号之前阻塞自
己,直到其他合作线程发来协调信号后才被唤醒并继续执行。这种协作线程之间相互等待对方消息或信号的协调关系称为线程同步。由于合作的每
一个线程都是独立地以不可预知的速度推进,这就需要相互协作的线程在某些协调点上协调各自的工作。7.3.3线程间的协作关
系与线程同步【例7.7】发送线程与接收线程。图7.10发送线程与接收线程通过缓冲区实现数据传递——演示传送数据的两个
线程之间存在的协作关系,演示在没有实现线程同步运行时存在的错误。7.3.3线程间的协作关系与线程同步两个线程
必须协调一致,发送线程必须在确定接收线程已经接收到数据之后,才能再次发送;接收线程每接收一个数据都要通知发送线程。协作线程之间
需要同步;【例7.7】发送线程与接收线程。7.3.3线程间的协作关系与线程同步2.线程同步线程互斥关系:一种特殊
的线程同步关系,即逐次使用互斥共享资源,也是对线程使用资源次序上的一种协调。7.3.3线程间的协作关系与线程同步3.
线程同步机制(2)设置信号量(semaphore)为共享变量约定一个信号量,设置信号量有多种状态。
测试信号量状态的操作称为P操作,改变信号量状态的操作称为V操作。这两种操作是互斥执行的,并且执行时不能被打断。7.3.3
线程间的协作关系与线程同步3.线程同步机制这样,交互的并发线程之间通过交换信号来达到调整相互速率,保证线程协调运行的
目的。利用信号量和P、V操作,既可以解决并发进程的竞争问题,又可以解决并发进程的协作问题。7.3.3线程间的协作关系与线
程同步4.Java的线程通信方法publicfinalvoidwait()throwsInterruptedExc
eption//等待publicfinalnativevoidwait(longtimeout)
throwsInterruptedException; //等待指定时间wait():使当前执行线程变为等
待状态;notify():唤醒一个正在等待的线程;notifyAll():是唤醒所有正在等待的线程.7.3.3
线程间的协作关系与线程同步【例7.8】采用信号量和同步方法使发送线程与接收线程同步运行。7
.3.3线程间的协作关系与线程同步图7.11发送线程与接收线程同步执行流程7.3.3线程间的协作关系与线程同
步【例7.9】发牌程序。——利用线程同步和线程调度技术,模拟发牌程序。对于4个人打扑克牌的游戏程序,自动发牌过程中
就蕴含着一个发牌线程与4个取牌线程间的两种同步问题,说明如下:①约定一个缓冲区,存放一张牌,为缓冲区是否为空设置一个
信号量(两个状态)。②有一个发牌线程,依次产生1-52中的一个数,每次只发出一张牌。③对于每发出的一张牌,同时有
4个取牌线程在争抢。④发牌线程的优先级应该高于取牌线程。7.3.3线程间的协作关系与线程同步图7.121个发牌
线程与4个取牌线程【例7.9】发牌程序。7.2.1Runnable接口与Thread类当目标对
象为空时,Thread类对象的run()方法为空。例如:Threadt1=newThread();//t1的
run()方法为当目标对象非空时,Thread对象将执行目标对象的run()方法。例如:Threadthread_odd=
newThread(odd,"奇数线程"); //th
read_odd实际执行odd的run()方法7.2.1Runnable接口与Thread类3.两种创建线程方式
的比较(1)继承线程Thread类声明一个线程类继承Thread类,并且必须覆盖Thread类的run()方法,说明线
程对象所执行的操作。优点:Thread类的子类对象就是线程对象,具有Thread类声明的方法,且具有线程体。缺点
:不适用于多重继承。——适用于单重继承,不适用于多重继承7.2.1Runnable接口与Thread类
3.两种创建线程方式的比较(2)实现Runnable接口——适用于多重继承一个实现Runnable接口的对
象本身不是线程对象,它作为一个线程对象的目标对象使用,因此,同时需要声明一个Thread线程对象。7.2.2线程对象的
生命周期1.Thread.State类声明的线程状态内部枚举类Thread.State表示线程状态。public
classThreadextendsObjectimplementsRunnable{publicstatic
enumThread.StateextendsEnum{publicstaticf
inalThread.StateNEW//新建态,已创建未启动publicstaticfinalThre
ad.StateRUNNABLE//运行态,正在执行publicstaticfinalThread.St
ateBLOCKED//阻塞态,等待监控锁publicstaticfinalThread.StateW
AITING//等待态,等待时间不确定publicstaticfinalThread.StateTIMED_
WAITING
//等待态,等待时间确定publicstaticfinalThre
ad.StateTERMINATED//终止态}publicStategetState()
//返回线程的当前状态}7.2.2线程对象的生命周期1.Thread.State类声明的线程
状态(1)新建态(NEW):newThread()创建的线程对象处于新建态
NEW,系统没有为其分配资源。(2)就绪态和运行态(RUNNABLE)从操作系统角度看,处于新建态
的线程启动后,进入就绪态,再由操作系统调度执行而成为运行态。从程序设计角度看,线程启动后即进入运行态,程序中不需要
区分就绪态或运行态。进入运行态的线程对象,系统执行线程对象的run()方法。7.2.2线程对象的生命周期
(3)阻塞态(BLOCKED)和等待态(WAITING/TIMED_WAITING)一个运行态的线程因某种
原因不能继续运行时,进入阻塞态或等待态。处于阻塞态或等待态的线程不能执行,即使处理器空闲也不能执行。只有当引起阻塞的原因被消除
,或等待的条件满足时,线程再转入运行态,重新进入线程队列排队等待运行,再次运行时将从暂停处继续运行。等待态:WAITIN
G:等待时间不确定。TIMED_WAITING:等待时间确定。7.2.2线程对象的生命周期(4)终止态(TE
RMINATED)线程对象停止运行未被撤销时是终止态。导致线程终止有两种情况:运行结束或被强行停止。当线程对象的run(
)方法执行结束时,该线程对象进入终止态,等待系统撤销对象所占用的资源;当进程因故停止运行时,该进程中的所有线
程将被强行终止。7.2.2线程对象的生命周期图7.4Java线程对象的状态及状态变化2.T
hread类中改变和判断线程状态的方法7.2.2线程对象的生命周期2.Thread类中改变和判断线程状态的方
法publicsynchronizedvoidstart()//启动已创建的线程对象publicfinalb
ooleanisAlive()//返回线程是否启动的状态只有处于新建态的线程对象才能调用start()方法启动,一个线程
对象只能启动一次,如果一个已启动的对象再次调用start()方法,则抛出IllegalThreadStateException;
当线程对象已启动为终止时,isAlive()返回true,此时该线程对象处于运行态、阻塞态、等待态之一;当一个线程对象未启动或已终
止,返回false。7.2.2线程对象的生命周期(2)线程睡眠sleep()方法使当前线程睡眠(停止执行)若
干毫秒,线程由运行态转入等待态,不可运行,睡眠时间到时可再次进入运行态。7.2.2线程对象的生命周期
(3)线程中断interrupt()方法设置当前线程对象运行中断标记,与之配合使用的还有两个判断线程是否中断的方法。
interrupt()方法为线程设置一个中断标记,以便于run()方法运行时使用isInterrupted()方法能够检
测到,此时线程在sleep()之类的方法中被阻塞时,由sleep()方法抛出一个InterruptException
异常,然后捕获这个异常以处理中断操作。7.2.2线程对象的生命周期【例7.3】设计滚动字演示线程状态及改变方法
。——演示线程对象的生命周期从创建到终止的过程,期间使用new()、start()、sleep()、interrupt
()等方法改变线程的状态。①声明自定义面板类为私有内部类并实现多个接口②线程状态变化7.2.3线程对象的优先
级publicstaticfinalintMIN__PRIORITY=1//最低优先级publicstatic
finalintMAX_PRIORITY=10//最高优先级publicstaticfinalintNOR
M_PRIORITY=5//默认优先级7.2.3线程对象的优先级2.Thread类中与线程优先级有关的方法有
以下2个:publicfinalintgetPriority()//获得线程优先级publicf
inalvoidsetPriority(intnewPriority)//设置线程优先级例7.1中:(1)设置奇数
线程的优先级为10;(2)设置奇数线程的优先级为1;7.2.4守护线程publicfinalvoidsetD
aemon(booleanon)//若on为true,则设置为守护线程,必须在启动线程前调用public
finalbooleanisDaemon()//判断是否为守护线程,若是,返回true;否则false
7.2.5定时器与图形动画设计动画设计需要使用线程技术,利用线程对象睡眠来控制画图和重画时间,睡眠时间长则移动较
慢,反之移动较快。当需要周期地执行某些操作,除了使用线程,还可以使用Swing的Timer组件。7.2.5定时
器与图形动画设计publicclassTimerimplementsSerializable{
publicTimer(intdelay,ActionListener1)
//delay设置延时的时间,1指定事件处理对象public
voidaddActionListener(ActionListener1)
//注册定时事件监听器
publicvoidremoveActionListener(ActionListener1)

//取消定时事件监听器publicintgetDelay()
//获得延时的时间间隔
publicvoidsetDelay(intdelay)
//设置延时的时间间隔publicvoidstart()
//启动定时器publicvoidstop()
//停止定时器publicvoidrestart()
//重新启动定时器}7.2.2线程对象的生命周期【例7.4】弹弹球,使用定时器实现图形动画。——使用Ti
mer定时器实现图形动画设计。在画布指定位置画多个圆,经过一段延时,再附近位置重画,看起来就像球在跑。其中使用
JSpinner组件调节弹弹球的移动速度。7.3线程的同步机制7.3.1交互线程7.3.2线程间的竞争关系与线程
互斥7.3.3线程间的协作关系与线程同步7.3线程的同步机制交互线程:如果并发执行的多个线程间需要共享资源或交
换数据,则该组线程为交互线程。交互线程并发执行时相互之间会干扰或影响其他线程的
执行结果,因此交互线程间需要有同步机制。7.3线程的同步机制交互线程间存在两种关系:竞争关系和协作关系。竞争关系的交
互线程间需要采用线程互斥方式解决共享资源冲突问题;
协作关系的交互线程间需要采用线程同步方式解决线程间通信及因执行速
度不同而引起的不同步问题。同步机制:线程互斥和线程同步线程互斥:用于竞争关系的交互线程;线程同步:用于协作关系的交
互线程线程互斥是线程同步的特殊情况。7.3.1交互线程1.无关线程与交互线程并发线程之间可能是无关的,也可能是交
互的;无关的并发线程:指它们分别在不同的变量集合上操作。一个线程的执行与其他并发线程的进展无关,即一个并发线程不会
改变另一个并发线程的变量值。交互的并发线程:指它们共享某些变量,一个线程的执行可能影响其他线程的执行结果,交互的并发
线程之间具有制约关系。因此,进程的交互必须是有控制的。7.3.1交互线程2.并发执行的交互线程间存在与时间有关的错误
无关的线程间并发执行时,不会产生与时间有关的错误。例如,对例7.1,奇数线程与偶数线程是两个并发执行的无关线程。程序每次执
行时,它们之间的执行次序可能会因线程调度而不同,但不会影响对方的结果值,奇数线程中绝不会输出偶数。7.3.1交互线
程2.并发执行的交互线程间存在与时间有关的错误交互的并发线程执行时,由于在不同时刻对同一个共享变量进行操作,线程之间
相互影响。因此结果往往取决于这一组并发线程的相对速度,各种与时间有关的错误就可能出现。例如,对银行账户的存款、取
款操作分别设计成线程,存款线程和取款线程对同一个账户数据进行操作,此时该账户成为共享变量,并发执行的多个存款、取款线程间
可能会产生与时间有关的错误。7.3.1交互线程【例7.5】银行账户的存/取款线程设计。——演示交互线程在对共享变
量进行操作时存在的问题。图7.7并发线程共享临界资源7.3.1交互线程【例7.4】银行账户的存/取款线程设计
。①运行结果不唯一,取决于线程调度如果存取款线程的执行没有被打断,即线程体中没有sleep延时,程序结果不确定。②线
程执行被打断时出现错误一个线程sleep让出处理器,让其他线程运行;其他并发执行线程修改了同一账户的共享数据,导致线程
再次运行时,该账户余额已经不是先前查看过的值,因此结果中查看金额、存取金额和剩余金额不相符,破坏了数据的完整性和一致性。错误
原因:多个线程交替访问同一共享变量,干扰其他线程的执行结果。如果串行执行,不会出现错误;如果两个
线程同时对不同账户对象操作,也不会出现错误;7.3.1交互线程7.3.2线程间的竞争关系与线程互斥1.线程间
的竞争关系一个线程得到资源,另一个线程必须等待,等待线程就是被阻塞的线程。在极端的情况下,被阻塞线程永远得不到访问权,从
而不能成功地终止。7.3.2线程间的竞争关系与线程互斥1.线程间的竞争关系例如:十字路口的交通信号灯控制。
如果四个方向都是绿灯,汽车抢行造成路堵——死锁;如果四个方向都是红灯,谁也不能走——饥饿。资源竞争出现两个问题:死锁(dea
dlock)问题:一组线程如果都获得了部分资源,还想得到其他线程所占用的资源,最终所有的线程都将陷入死锁;饥饿(starvat
ion)问题:一个线程由于其他线程总是优先于它而被无限期拖延。7.3.2线程间的竞争关系与线程互斥1.线程间的竞争
关系由于操作系统负责资源分配,所以操作系统必须协调好线程对资源的争用。 操作系统要保证这些线程能互斥地访问临界资源,
既要解决饥饿问题,又要解决死锁问题。7.3.2线程间的竞争关系与线程互斥2.线程互斥和临界区管理临界资源(
criticalresource):共享变量代表的资源;临界区(criticalsection):并发线程中与共享变量有关的
程序段;7.3.2线程间的竞争关系与线程互斥操作系统对共享一个变量的若干线程进入各自临界区有以下3个调度原则:一次至
多一个线程能够在临界区内。不能让一个线程无限期地留在临界区内。不能强迫一个线程无限期地等待进入它的临界区。特别地,进入临界
区的任一线程不能妨碍正等待进入的其他线程的进展。临界区的调度原则:无空等待、有空让进、择一而入、算法可行。算法可行:指不能因为
所选的调度策略造成线程饥饿甚至死锁。即保证各线程对共享变量的访问是互斥的,那么就不会
造成与时间有关的错误。2.线程互斥和临界区管理第7章多线程多线程进程的操作系统支
持多线程的并发程序设计。多线程的并发程序设计:即一个程序可分成若干个并发执行的
进程,一个进程可再分成若干个并发
执行的线程。第7章多线程Java支持多线程的并发程序设计。Java语言提供线程类
和接口,用于创建、管理和控制线程对象。7.1操作系统中的进程和线程7.2Java的线程对象7.3线程的同步机制第7
章多线程7.1操作系统中的进程和线程7.1.1进程7.1.2线程7.1.3并发程序设计1.进程的定义
和属性7.1.1进程进程(process):一个可并发执行的具有独立功能的程序关于某个数据集
合的一次执行过程,也是操作系统进行资源分配和保护的基本单位。结构性—进程包含了数据集合和运行于其上的
程序。每个进程至少由三要素组成:程序块、数据块和进程控制块。进程控制块(ProcessControlBlock,PCB)用于
描述和记录进程的动态变化过程使进程能正确运行。共享性—同一程序同时运行于不同数据集合上时构成不同的进程,或者说,多个不同的进程可
以共享相同的程序。所以,程序和进程不是一一对应的。7.1.1进程动态性—进程是程序在数据集合上的一次执行过程,是动态概念
,它有生命周期,由创建而产生,由调度二执行,由撤销而消亡。而程序是一组有序指令序列,是静态概念,程序作为一种系统资源是永久存在的。
独立性—进程既是系统中资源分配和保护的基本单位,也是系统调度的独立单位(单线程进程)。凡是未建立进程的程序,都不能作为独立单位参
与运行。每个进程都可以各自独立的速度在CPU上推进。1.进程的定义和属性7.1.1进程1.进程的定义和属性并发性
—进程可以并发地执行,进程的并发性能够提高资源利用率和系统效率。进程的并发性是指一组进程的执行在时间上是重叠的。对于一个单处理器的
系统来说,m个进程P1,P2,…,Pm是轮流占用处理器并发地执行。因此,进程的执行是可以被打断的,进程执行完一条指令后在执行
下一条指令前,可能被迫让出处理器,由其他若干进程执行若干条指令后才能再次获得处理器而执行。制约性—并发进程之间存在着制约关系,进
程在进行的关键点上需要相互等待或互通消息,以保证程序执行的可再现性和计算结果的唯一性。7.1.1进程2.进程的状态就
绪(ready)态—进程具备运行条件,等待系统分配处理器以便运行。运行(running)态
—进程占用处理器正在运行。阻塞(blocked)态—进程不具备运行条件,正在等待某个事
件的完成。进程是活动的且有状态变化的,进程的生命周期包括创建、等待、运行和撤销等阶段,采用一组状态刻画进程在其生命
周期中的变化,进程状态如下:进程在创建后处于就绪状态,获得处理器时处于运行态,运行中因等待条件处于阻塞态。
7.1.2线程1.引入线程机制的动机和思路早期操作系统中,进程是系统进行资源分配的基本单位,也是处理器调度的基本
单位,进程在任一时刻只有一个执行控制流,这种结构的进程称为单线程进程。例如:MS-DOS支持单用户进程,进程是单线程的;
传统的UNIX支持多用户进程,每个进程也是单线程的。单线程进程调度时存在的问题:进程时空开销大,进程通信
代价大,进程并发粒度粗、不适合于并行计算等。7.1.2线程1.引入线程机制的动机和思路线程机制的基本思路
:把进程的两项功能——“独立分配资源”和“被调度分派执行”分离,前一项任务仍由进程完成,后一项任务交给称为线程的实体完成。
这样,进程作为系统资源分配与保护的独立单位,不需要频繁地切换;线程作为系统调度和分派的的基本单位,会被频繁地调度和切换。7.
1.2线程2.线程的定义和属性线程(thread):操作系统进程中能够独立执行的实体(控制流),
是处理器调度和分派的基本单位。线程是进程的组成部分,每个进程内允许包含多个并发执行的线程。同一个进程中的所有线程共享
进程获得的主存空间和资源,但不拥有资源。7.1.2线程7.1.2线程线程的主要特性:并发性—同一进程的多
个线程可在一个/多个处理器上并发或并行地执行,而进程之间的并发执行演变为不同进程的线程
之间的并发执行。共享性—同一个进程中的所有线程共享但不拥有进程的状态和资源,且驻留在进程的同一个主存地址空
间中,可以访问相同的数据。所以,线程之间需要有通信和同步机制。7.1.2线程
动态性—线程是程序在相应数据集合上的一次执行过程,它有生命周期,也经历各种状态变化,由创建而产生,至
撤销而消亡。每个进程被创建时,至少同时为其创建一个线程,需要时线程再创建其他线程。进程的终止将导致进程中
所有线程终止。线程的主要特性:结构性—线程是操作系统中的基本调度和分派单位,因此它具有唯一的标识符和线程控制块,其中包含
调度所需的一切私有信息。7.1.2线程3.线程的状态图7.2线程的5种状态及状态转换7.1.2
线程4.线程的并发性在单处理器上,一组线程的执行在时间上是重叠的,它们的操作是交叉执行的,称这些线程是并发执
行的。从宏观上看,并发性反映出一个时间段中有几个线程都处于运行还未运行结束状态,且这些线程都在同一个处理器上运行;从微观上看
,任一时刻仅有一个线程在处理器上运行。并发的实质:一个处理器在多线程之间的多路复用,并发是对
有限的物理资源强制行使多用户共享,消除计算机部件之间的互等现象,
以提高系统资源利用率。7.1.2线程5.线程调度问题:当有多个线程处于就绪态时,它们排队等待处理器
资源。对于单处理器,任一时刻只有一个线程能够占用处理器执行。因此,按什么原则决定就绪队列
中的哪个线程能获得处理器则是操作系统的重要问题,这就是线程调度的任务。线程调度的功能:
按照某种原则选择一个线程使它获得处理器运行。7.1.2线程线程调度采用剥夺方式,当一个线程正在一个处理器上执行时
,操作系统可以根据规定的原则剥夺它的处理器,而把处理器分给其他线程使用。剥夺原则:一是高优先级线程剥夺低优先级线程运行
;二是当运行线程时间使用完后被剥夺处理器。可以避免一个线程长时间独占处理器,能给线
程提供较好的服务。7.1.3并发程序设计1.顺序程序设计(sequentialprogramming)顺序程序设计
方法:程序模块按语句次序顺序执行。顺序程序设计的特性:执行的顺序性环境的封闭性执行结果的确定性计算结果的可再现性顺序程
序设计的顺序性、封闭性、确定性和再现性表明了程序与计算(程序的执行)是一一对应的,给程序的编制、调试带来很大方便,其缺
点是计算机系统效率不高。7.1.3并发程序设计2.并发程序设计(concurrentprogramming)并发程
序设计方法:将一个程序分成若干个可同时执行的程序模块,每个程序模块和它执行时所处理的数据就组成一个进程。并发程序设计
的特性:并发性—进程的执行在时间上可以重叠,在单处理器系统中可以并发执行;在多处理器系统中可以并行执行。
共享性—它们可以共享变量,通过引用这些共享变量就能互相交换信号,程序的运行环境不再是封闭的。7.1.3
并发程序设计并发程序设计的特性:制约性—进程并发执行或协作完成同一任务时,会产生相互制约关系,必须对
它们并发执行的次序(即相对执行速率)加以协调。交互性—由于进程可共享变量,一个程序的执行可能影响其他
程序的执行结果,因此这种交互必须是有控制的,否则会出现不正确的结果。即使程序自身能正确运行,
由于程序的运行环境不再是封闭的,程序结果仍可能是不确定的,计算过程具有不可再现性。2
.并发程序设计(concurrentprogramming)7.1.3并发程序设计采用并发程序设计的目的是:
充分发挥硬件的并行性,消除处理器和I/O设备的互等现象,提高系统效率。2.并发程序设计(concurrentprogra
mming)并发多线程程序设计是指:在一个进程中包含多个并发执行的控制流。主
要优点:使系统性能获得很大提高,具体表现为快速切换线程、减少系统管理开销、线程通信易于实现、并发
程度提高、节省内存空间等。7.2Java的线程对象7.2.1Runnable接口与Thread类7.2.2
线程对象的生命周期7.2.3线程对象的优先级7.2.4守护线程7.2.5定时器与图形动画设计7.2Ja
va的线程对象1.Java支持内置的多线程机制。Java语言包中的Runnable接口约定线程的执行方法;Thread类提供创建、管理和控制线程对象的方法。2.线程对象执行的方法是java.lang.Runnable接口中的run()方法。3.就像应用程序必须从main()开始执行一样,一个线程必须从run()方法开始执行。7.2.1Runnable接口与Thread类1.Runnable接口run()是线程的执行方法,一个线程对象必须实现run()方法以描述该线程的所有活动及执行的操作,已实现的run()方法称为该线程对象的线程体。7.2.1Runnable接口与Thread类2.Thread线程类publicclassThreadextendsObjectimplementsRunnable{publicThread()//构造方法publicThread(Stringname)//name指定线程名publicThread(Runnabletarget)//target指定线程的目标对象publicThread(Runnabletarget,Stringname)7.2.1Runnable接口与Thread类2.Thread线程类7.2.1Runnable接口与Thread类线程对象由Thread类或其子类声明,构造线程对象时,可为其指定线程名;如果没有指定线程名,则Java自动提供一个线程名。线程对象执行run()方法,该run()方法既可以由线程自身提供,也可以由目标对象提供,目标对象指实现了Runnable接口的对象。2.Thread线程类【例7.1】声明继承Thread类的奇数/偶数序列线程。——演示通过继承Thread类设计线程。7.2.1Runnable接口与Thread类声明自定义线程类NumberThread继承Thread类,其中成员变量k设置序列初始值,run()方法覆盖Thread类的run()方法,提供线程执行的线程体,输出一个奇数(或偶数)序列。①main()线程是首先启动执行的线程②两个线程交替运行7.2.1Runnable接口与Thread类图7.3一个进程中3个线程并发执行7.2.1Runnable接口与Thread类【例7.2】声明实现Runnable接口的奇数/偶数序列线程。——演示通过实现Runnable接口方式设计线程。
献花(0)
+1
(本文系信息检索04...首藏)