11 第十一课:线程
第九课《线程》
线程的优先级
JAVA提供一个线程调度器来监控程序中处于就 绪状态的线程。按照线程的优先级别来决定哪个 线程来执行。 线程的优先级别从1---10,默认级别是5. Thread.MIN_PRIORITY = 1 Thread.MAX_PRIORITY = 10 Thread.NORM_PRIORITY = 5 设置和获得线程优先级的方法 int getPriority() void setPriority(int Priority)
线程同步 当多个线程同时对一个资源进行操作的时 候,为了保证资源信息的完整性和正确性 ,引进了同步这个概念。 实例:用存折和银行卡同时到银行取钱 通过同步的方法把资源锁定,可以有 效的避免这种情况的发生。 实例:TestSync.java TestSynch.java
12
2007 iSoftStone Holdings Ltd. All Rights Reserved.
第十一课《线程》
第十一课《线程》 11.1 多线程基本概念 11.2 创建线程的方式 11.3 线程的挂起与唤醒 11.4 多线程问题 11.5 小结
2
2007 iSoftStone Holdings Ltd. All Rights Reserved.
线程的基本概念
线程是一个程序里面不同的执行路径 每一个路径叫一个分支,一个分支代表一个线程 所谓进程是指程序的一次执行过程,可以包含多个线程。 进程是一个静态的概念。 一个class文件,一个exe文件都叫一个进程 平时说的进程的执行,是指进程里的主线程开始执行了。 如果把程序看作一支曲谱,进程可以理解为对这支曲谱的 演奏过程。 一个程序至少包含一个进程,一个进程至少包含一个线程。 实例:TestThread.java
11_linux线程专题讲座王保明
linux线程-应用编程-专题讲座written by 王保明线程概念1线程概念fork和创建新线程的区别❑当一个进程执行一个fork调用的时候,会创建出进程的一个新拷贝,新进程将拥有它自己的变量和它自己的PID。
这个新进程的运行时间是独立的,它在执行时几乎2线程模型N:1用户线程模型❑在N:1线程模型中,内核不干涉线程的任何生命活动,也不干涉同一进程中的线程环境切换。
❑在N:1线程模型中,一个进程中的多个线程只能调度到一个CPU,这种约束限制了可用的并行总量。
第二个缺点是如果某个线程执行了一个“阻塞式”操作(如read),那么,进程中的所有线程都会阻塞,直至那个操作结束。
为此,一些线程的实现是为这些阻塞式函数提供包装器,用非阻塞版本替换这些系统调用,以消除这种限制。
1:1核心线程模型❑在1:1核心线程模型中,应用程序创建的每一个线程都由一个核心线程直接管理。
❑OS内核将每一个核心线程都调到系统CPU上,因此,所有线程都工作在“系统竞争范围”。
❑这种线程的创建与调度由内核完成,因为这种线程的系统开销比较大(但一般来说,比进程开销小)N:M混合线程模型N:M混合线程模型提供了两级控制,将用户线程映射为系统的可调度体以实现并行,这个可调度体称为轻量级进程(LWP:lightweight process),LWP再一一映射到核心线程2线程API线程基本posix api线程客户端测试框架多线程服务器框架3线程属性其他说明4线程互斥和同步基本概念posix互斥锁posix条件变量pthread_mutex_unlock(&mutex);•使用条件变量之前要先进行初始化。
可以在单个语句中生成和初始化一个条件变量如:•pthread_cond_t my_condition=PTHREAD_COND_INITIALIZER;(用于进程间线程的通信)。
也可以利用函数pthread_cond_init动态初始化pthread_cond_destroy函数可以用来摧毁所指定的条件变量,同时将会释放所给它分配的资源。
Java学习笔记之--线程
1.一个进程包含多个线程,每一个线程都有相对独立的资源、生存周期。
在进程中,可以有一个或多个线程,如果程序员不创建线程对象,那么系统会自动创建一个主线程。
2.进程是同时进行的,每个进程都都独立的地址空间,而线程是分时进行的,他们共用地址空间,并且分享同一个进程,但由于执行速度很快,所以感觉不出来,感觉好像是线程也同时进行一样。
3.线程有五种状态:新建、就绪、运行、阻塞和死亡。
4.创建线程可以通过继承Thread类来完成。
Thread类的构造方法:Thread类的常用方法:5.利用Thread的子类创建线程package aaa;public class myThread extends Thread {private static int count=0;public myThread(String name) {super(name);}public void run(){int i=0;for(i=0;i<100;i++){count=count+1;System.out.println("my name is"+getName()+"count="+count);//其中getName()是Thread中的方法,用于返回现在正在运行的线程的名字try {sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args){myThread first,second;first=new myThread("First Thread");second=new myThread("Second Thread");first.start();second.start();//其实两个线程是同时启动的。
线程的基础知识
线程的基础知识1. 进程与线程有那些区别和联系?每个进程至少需要一个线程。
进程由两部分构成:进程内核对象,地址空间。
线程也由两部分组成:线程内核对象,操作系统用它来对线程实施管理。
线程堆栈,用于维护线程在执行代码时需要的所有函数参数和局部变量。
进程是不活泼的。
进程从来不执行任何东西,它只是线程的容器。
线程总是在某个进程环境中创建的,而且它的整个寿命期都在该进程中。
如果在单进程环境中,有多个线程正在运行,那么这些线程将共享单个地址空间。
这些线程能够执行相同的代码,对相同的数据进行操作。
这些线程还能共享内核对象句柄,因为句柄表依赖于每个进程而不是每个线程存在。
进程使用的系统资源比线程多得多。
实际上,线程只有一个内核对象和一个堆栈,保留的记录很少,因此需要很少的内存。
因此始终都应该设法用增加线程来解决编程问题,避免创建新的进程。
但是许多程序设计用多个进程来实现会更好些。
2. 如何使用_beginthreadex函数?使用方法与CreateThread函数相同,只是调用参数类型需要转换。
3. 如何使用CreateThread函数?当CreateThread被调用时,系统创建一个线程内核对象。
该线程内核对象不是线程本身,而是操作系统用来管理线程的较小的数据结构。
使用时应当注意在不需要对线程内核进行访问后调用CloseHandle函数关闭线程句柄。
因为CreateThread函数中使用某些C/C++运行期库函数时会有内存泄漏,所以应当尽量避免使用。
参数含义:lpThreadAttributes 如果传递NULL该线程使用默认安全属性。
如果希望所有的子进程能够继承该线程对象的句柄,必须将它的bInheritHandle成员被初始化为TRUE。
dwStackSize 设定线程堆栈的地址空间。
如果非0,函数将所有的存储器保留并分配给线程的堆栈。
如果是0,CreateThread就保留一个区域,并且将链接程序嵌入.exe文件的/ST ACK链接程序开关信息指明的存储器容量分配给线程堆栈。
线程的基本用法
线程的基本用法1线程与进程基本关系1.1进程概念进程是表示资源分配的基本单位,又是调度运行的基本单位。
例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括各种表格、内存空间、磁盘空间、I/O 设备等。
然后,把该进程放人进程的就绪队列。
进程调度程序选中它,为它分配CPU以及其它有关资源,该进程才真正运行。
所以,进程是系统中的并发执行的单位。
在Mac、Windows NT等采用微内核结构的操作系统中,进程的功能发生了变化:它只是资源分配的单位,而不再是调度运行的单位。
在微内核系统中,真正调度运行的基本单位是线程。
因此,实现并发功能的单位是线程。
1.2线程概念线程是进程中执行运算的最小单位,亦即执行处理机调度的基本单位。
如果把进程理解为在逻辑上操作系统所完成的任务,那么线程表示完成该任务的许多可能的子任务之一。
例如,假设用户启动了一个窗口中的数据库应用程序,操作系统就将对数据库的调用表示为一个进程。
假设用户要从数据库中产生一份工资单报表,并传到一个文件中,这是一个子任务;在产生工资单报表的过程中,用户又可以输人数据库查询请求,这又是一个子任务。
这样,操作系统则把每一个请求――工资单报表和新输人的数据查询表示为数据库进程中的独立的线程。
线程可以在处理器上独立调度执行,这样,在多处理器环境下就允许几个线程各自在单独处理器上进行。
操作系统提供线程就是为了方便而有效地实现这种并发性1.3引入线程的好处(1)易于调度。
(2)提高并发性。
通过线程可方便有效地实现并发性。
进程可创建多个线程来执行同一程序的不同部分。
(3)开销少。
创建线程比创建进程要快,所需开销很少。
(4)利于充分发挥多处理器的功能。
通过创建多线程进程(即一个进程可具有两个或更多个线程),每个线程在一个处理器上运行,从而实现应用程序的并发性,使每个处理器都得到充分运行。
1.4进程和线程的关系一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
线程
内核级线程(2)
线程执行中可通过内核创建线程 原语来创建其他线程,这个应用 的所有线程均在一个进程中获得 支持。
内核要为整个进程及进程中的单 个线程维护现场信息,应在内核 中建立和维护PCB及TCB,内核的 调度是在线程的基础上进行的。
内核级线程主要优点
多处理器上,内核能同时调度同一 进程中多个线程并行执行。
用户 堆栈
用户 地址空间
系统 堆栈
用户地址空间 进程控制块
用户堆栈 系统堆栈
进程
管理者 执行序列
管理和执行相分离的进程模型
用户地址空间
进程控制块
管理者
执行序列
共享
执行控制
执行控制
执行序列
用户堆栈 系统堆栈
用户堆栈 系统堆栈
进程
多线程进程的内存布局
多线程进程模型
进程 控制块
用户 地址空间
线程1 线程控制块
进程和线程
⑵用多个相互独立的进程,每个进程负责 一个请求。
这种方案不会出现⑴的矛盾和浪费局面, 但是显然这些进程间需要大量的和复杂 的共享机制,而且需要大量的进程,每 个进程都需要占用一套完整的进程管理 信息,这些进程频繁地动态建立和撤消 ,频繁地进行进程切换。这些开销是很 大的,而考虑到这些进程处理的大部分 数据是相互共享的,运行的程序也是同 一个程序,这种开销就值得研究了。
进程和线程
可以看出上述在进程模型下的3种方案都不 能很好地解决和实现“基于同一数据空 间来处理多个请求”的需要。
线程模型正是为了更好地解决和实现这种 基于同一数据空间来处理多个请求”的 需要,而提出的。
为“同时多请求”服务的4种方 案
模
型
进 单进程顺序处理
操作系统-线程(Threads)的基本概念
2
第一章 操作系统引论
② 进程同时又是一个可独立调度和分派的基本单位,一 个进程要能独立运行,它还必须是一个可独立调度和分派的 基本单位。每个进程在系统中有唯一的PCB,系统可根据其 PCB感知进程的存在,也可以根据其PCB中的信息,对进程 进行调度,还可将断点信息保存在其PCB中。反之,再利用 进程PCB中的信息来恢复进程运行的现场。正是由于进程有 这两个基本属性,才使进程成为一个能独立运行的基本单位, 从而也就构成了进程并发执行的基础。
8
第一章 操作系统引论
3. 多线程OS中的进程属性 通常在多线程OS中的进程都包含了多个线程,并为它们 提供资源。OS支持在一个进程中的多个线程能并发执行,但 此时的进程就不再作为一个执行的实体。多线程OS中的进程 有以下属性: (1) 进程是一个可拥有资源的基本单位。 (2) 多个线程可并发执行。 (3) 进程已不是可执行的实体。
5
第一章 操作系统引论
2.7.2 线程与进程的比较 1. 调度的基本单位 2. 并发性 3. 拥有资源 4. 独立性 5. 系统开销 6. 支持多处理机系统
6
第一章 操作系统引论
2.7.3 线程的状态和线程控制块1. 线程运行的三个状态 与传统的进程一样,在各线程之间也存在着共享资源和
相互合作的制约关系,致使线程在运行时也具有间断性。相 应地,线程在运行时也具有下述三种基本状态:
3
第一章 操作系统引论
2. 程序并发执行所需付出的时空开销 为使程序能并发执行,系统必须进行以下的一系列操作: (1) 创建进程,系统在创建一个进程时,必须为它分配 其所必需的、除处理机以外的所有资源,如内存空间、I/O 设备,以及建立相应的PCB; (2) 撤消进程,系统在撤消进程时,又必须先对其所占 有的资源执行回收操作,然后再撤消PCB; (3) 进程切换,对进程进行上下文切换时,需要保留当 前进程的CPU环境,设置新选中进程的CPU环境,因而须花 费不少的处理机时间。
冀教版小学信息技术五年级上册《第11课 问题的抽象》课堂练习及知识点
冀教版小学信息技术五年级上册《第11课问题的抽象》课堂练习及知识点知识点归纳:1. 问题抽象的概念:理解问题抽象是将复杂问题简化,提取关键信息和步骤的过程。
2. 抽象的步骤:识别问题的核心要素,忽略非关键信息,建立模型或规则。
3. 抽象的意义:帮助我们更好地理解和解决复杂问题,是编程思维的重要组成部分。
4. 实例分析:通过具体的信息技术问题或编程案例,理解抽象的应用。
课堂练习:判断题:1. 问题抽象就是把所有细节都去除,只留下最简单的内容。
(T/F)2. 抽象的过程有助于我们更快速、更准确地解决问题。
(T/F)3. 在编程中,定义变量、编写函数都是抽象的过程。
(T/F)选择题:4. 以下哪个是问题抽象的例子?(A/B/C/D)A. 设计算法时,只关注关键步骤,忽略次要操作B. 设计游戏时,先创建基本规则,再添加复杂细节C. 编写故事时,先确定主要角色和情节,再填充细节D. 所有以上都是5. 抽象能够帮助我们做什么?(A/B/C/D)A. 提高解决问题的效率B. 降低理解问题的难度C. 使问题更易于处理D. 以上所有6. 在编程中,如何实现问题的抽象?(A/B/C/D)A. 使用变量存储数据B. 创建函数来封装操作C. 设计类来表示对象D. 以上所有填空题:7. 问题抽象是将复杂问题______和______的过程。
(简化,关键信息)8. 抽象的关键步骤是______问题的核心要素和______非关键信息。
(识别,忽略)9. 在编程中,我们通过______和______来实现问题的抽象。
(定义变量,编写函数)简答题:10. 请解释问题抽象在解决复杂问题时的作用,并给出一个例子。
11. 描述一个你在学习信息技术或编程时遇到的问题,你是如何通过抽象来解决它的?参考答案:判断题:1. T2. T3. T选择题:4. D5. D6. D填空题:7. 简化,关键信息8. 识别,忽略9. 定义变量,编写函数简答题:10. 问题抽象在解决复杂问题时,能帮助我们将注意力集中在问题的核心上,忽略不重要的细节,使问题更易于理解和处理。
线程详解
线程(thread, 台湾称执行绪)是"进程"中某个单一顺序的控制流。
也被称为轻量进程(lightweight processes)。
计算机科学术语,指运行中的程序的调度单位。
线程是进程中的实体,一个进程可以拥有多个线程,一个线程必须有一个父进程。
线程不拥有系统资源,只有运行必须的一些数据结构;它与父进程的其它线程共享该进程所拥有的全部资源。
线程可以创建和撤消线程,从而实现程序的并发执行。
一般,线程具有就绪、阻塞和运行三种基本状态。
在多中央处理器的系统里,不同线程可以同时在不同的中央处理器上运行,甚至当它们属于同一个进程时也是如此。
大多数支持多处理器的操作系统都提供编程接口来让进程可以控制自己的线程与各处理器之间的关联度(affinity)。
有时候,线程也称作轻量级进程。
就象进程一样,线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。
但是,与分隔的进程相比,进程中的线程之间的隔离程度要小。
它们共享内存、文件句柄和其它每个进程应有的状态。
进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。
一个进程中的多个线程共享相同的内存地址空间,这就意味着它们可以访问相同的变量和对象,而且它们从同一堆中分配对象。
尽管这让线程之间共享信息变得更容易,但您必须小心,确保它们不会妨碍同一进程里的其它线程。
Java 线程工具和API看似简单。
但是,编写有效使用线程的复杂程序并不十分容易。
因为有多个线程共存在相同的内存空间中并共享相同的变量,所以您必须小心,确保您的线程不会互相干扰。
一、线程的概念一般来说,我们把正在计算机中执行的程序叫做"进程"(Process) ,而不将其称为程序(Program)。
所谓"线程"(Thread),是"进程"中某个单一顺序的控制流。
新兴的操作系统,如Mac,Windows NT,Windows 95等,大多采用多线程的概念,把线程视为基本执行单位。
多线程课件专题知识讲座
线程旳优缺陷
优点:共享旳数据使线程之间旳通信愈加简朴而有效, 创建和销毁线程旳开销要比进程小得多。
缺陷:危险,轻易犯错。
6
11.2 线程旳状态与生命周期
一种线程旳生命周期一般要经历5个状态 创建状态(born) 就绪状态(ready) 运营状态(running) 阻塞状态(blocked,waiting,sleeping) 死亡状态(dead)
原来处于阻塞状态旳线程,被解除阻塞后也将进入就绪 状态。
10
11.2 线程旳状态与生命周期
3. 运营状态(Running)
当就绪状态旳线程被调度并取得处理器资源时,便进 入运营状态。
处于运营中旳线程,因调用了措施yield()会自动放弃 CPU而进入就绪状态。从而使其他就绪旳线程有运营 旳机会。
Thread类实现了Runnable接口中旳run措施,但措施体 为空。
17
11.4.1 Thread类和Runnable接口简介
3.Thread类旳构造措施
Thread(String threadName) 为• 新利创用建构旳造线措程施对创象建指新定线一程种对字象符之串后名,称进t入hr线ea程dN旳a生me。
具有较高优先级旳线程,完毕旳任务较紧急,因而应优 先于较低优先级旳线程分配处理器时间。
每个新创建线程均继承创建线程旳优先级。 线程旳优先级旳设置或读取
用setPriority(int priority)设置线程旳优先级 用getPriority()措施取得线程旳优先级
14
11.3 线程优先级与线程调度策略
码加载、执行、到执行完毕旳一种完整过程,这个过程 也是进程本身从产生、发展到消灭旳过程)。进程由操作 系统来管理。 线程(thread):进程中可独立执行旳子任务,一种进程能 够具有一种或多种线程,每个线程都有一种唯一旳标识 符。 多线程:当需要在一种程序中同步执行几段代码,以完 毕不同旳任务时,就会用多线程技术。多线程由程序负责 管理。
c语言线程的概念
c语言线程的概念
在C语言中,线程(thread)是计算机中独立运行的最小单位,也可以看
作是操作系统分配CPU时间的基本单位。
线程具有以下特点:
1. 线程是轻量级的进程,由线程ID、程序计数器、寄存器集合和堆栈组成。
2. 线程是进程中的一个实体,是系统独立调度和分配的基本单位。
线程自己几乎不拥有资源,只拥有在运行中必不可少的资源,但它可与进程中的其他线程一起共享进程的全部资源。
3. 引入线程的目的是减小程序在并发执行时造成的时空开销,提高系统的并发性能。
在Linux系统中,多线程可以通过第三方线程库来实现。
一个进程中的多个线程可以共享这些资源:可执行的指令、静态数据、进程中打开的文件描述符、信号处理函数、当前工作目录、用户ID、用户组ID等。
在NPTL线程库中提供了创建线程、删除线程、控制线程等基本操作。
如需更多关于C语言线程的信息,建议查阅相关书籍或论坛教程。
-多线程-
}
案例:实现Runnable接口编写线程类
案例:借助Thread类启动线程
继承Thpracekagae dcn类.sxt.s与hare;实现Runnable接口的区别
继示J承a例vT1ah6中-r7e的ad类类具实有现pu单多bpl继i线ucb承cs程liluca的ps有Tesi特rc一T(kni点eca定tkmTe,的hetTr)如;eh局ard果e限a(Sd一性trei个nxgt类enna继dms承eT)h{了reaTdh{read类那么就不能再继承其它的类了,所以
创f建orTh(irnetaid对= 0象; ,i <并5给; i+线+程) {起个名字
Thread(Runnable target) Thread(Runnable target, String name)
根据RuSnynsatbelme接.o口ut的.pr实in现tln类("创==建==Th=r=e=a=d=对=象==main中的i=" + i); }
}
TicketThread t3=new TicketThread("C窗口");
}
t1.start();//启动线程,开始售票
看到每个窗口各卖了5张票,3个窗口一共卖了t125.s张ta,rt()产; 生的原因是三个线程类的对象,
每个对象都有一个独立的属性ticket
t3.start(); }
}
继承Thread类与实现Runnable接口的区别
} }
线程的生命周期
新生状态:一个线程类使用new关键字创建完对象,在堆内存开辟内存空间 ,所以说处 于新生状态的线程有自己的内存空间
线程的作用
java线程的作用这是javaeye上非常经典的关于线程的帖子,写的非常通俗易懂的,适合任何读计算机的同学.线程同步我们可以在计算机上运行各种计算机软件程序。
每一个运行的程序可能包括多个独立运行的线程(Thread)。
线程(Thread)是一份独立运行的程序,有自己专用的运行栈。
线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。
当多个线程同时读写同一份共享资源的时候,可能会引起冲突。
这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。
同步这个词是从英文synchronize(使同时发生)翻译过来的。
我也不明白为什么要用这个很容易引起误解的词。
既然大家都这么用,咱们也就只好这么将就。
线程同步的真实意思和字面意思恰好相反。
线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。
因此,关于线程同步,需要牢牢记住的第一点是:线程同步就是线程排队。
同步就是排队。
线程同步的目的就是避免线程“同步”执行。
这可真是个无聊的绕口令。
关于线程同步,需要牢牢记住的第二点是“共享”这两个字。
只有共享资源的读写访问才需要同步。
如果不是共享资源,那么就根本没有同步的必要。
关于线程同步,需要牢牢记住的第三点是,只有“变量”才需要同步访问。
如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。
至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。
关于线程同步,需要牢牢记住的第四点是:多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步。
为了加深理解,下面举几个例子。
有两个采购员,他们的工作内容是相同的,都是遵循如下的步骤:(1)到市场上去,寻找并购买有潜力的样品。
(2)回到公司,写报告。
这两个人的工作内容虽然一样,他们都需要购买样品,他们可能买到同样种类的样品,但是他们绝对不会购买到同一件样品,他们之间没有任何共享资源。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
World " + j++);
public class ThreadTest { public static void main(String args[]) { Xyz1 r1 = new Xyz1(); Xyz2 r2 = new Xyz2(); Thread t = new Thread(r1); t.start(); t = new Thread(r2); t.start(); } }
实例分析 1
问题的描述: 创建和启动Java线程 解决方案: 以2种方式创建线程
实现ng.Runnable接口
实现run()方法 将这个新类的实例作为Thread类的构造方法的参数,创建Thread 类的实例。
class Xyz implements Runnable { int i;
对象锁与同步(synchronized)
每个对象都有一个标志,它被认为是”锁标志”. synchronized允许和锁标志交互。 要使锁有效,所有存取共享数据的方法必须在 同一把锁上同步。 锁是对象级的。成员没有所谓的锁。
下面是对前一示例的修改: public void push(char c) { synchronized(this) { data[idx] = c; idx++; } } public char pop() { synchronized(this) { idx--; return data[idx]; } }
问题描述 2个线程的调度
class Xyz1 implements Runnable { int i; public void run() { while (true) { System.out.println("Hello " + i++); if( i == 25){ try { Thread.sleep(10); }catch (InterruptedException e) { } } if (i == 50) break; } } }
}
public class ThreadTest { public static void main(String args[]) { Xyz r = new Xyz(); //Thread t = new Thread(r); r.start(); } }
class Xyz2 implements Runnable { int j = 100; public void run() { while (true) { System.out.println(" if (j == 150) break; } : 在前一个练习的基础上编写另外一个线程, 该线程打印100到1之间的递减过程.要求: 在第一个线程打印到50时,第一个线程暂停 直至第二个线程结束.
多个线程共享同一数据 当多个线程共享同一资源时,它们操作会 竞争同一资源,出现一些意料之外的错误。
释放锁标志
线程执行到synchronized()代码块末尾时释放 synchronized()代码块抛出中断或异常时自动 释放 由于等待一个对象的锁标志的线程在得到标志 之前不能恢复运行,所以让持有锁标志的线程 在不再需要的时候返回标志是很重要的。 锁标志将自动返回给它的对象。持有锁标志的 线程执行到synchronized()代码块末尾时将释 放锁。Java技术特别注意了保证即使出现中断 或异常而使得执行流跳出synchronized()代码 块,锁也会自动返回。
继承ng.Thread类
覆盖Thread类的run()方法 创建该子类的实例 class Xyz extends Thread { int i;
public void run() { while (true) { System.out.println("Hello " + i++); if (i == 50) break; } }
2. 继承Thread类 当一个run()方法体现在继承Thread的类中,用 this指向实际控制运行的Thread实例。因此,代 码不再需要使用如下控制: Thread.currentThread().join(); 而可以简单地用: join(); 因为代码简单了一些,许多Java编程语言的程序 员使用扩展Thread的机制。注意:如果你采用这 种方法,在你的代码生命周期的后期,单继承模 型可能会给你带来困难。
public class Producer extends Thread{ MyStack mt; char[] mc = {'m','s','t','a','c','k'}; public Producer(MyStack mt){ this.mt = mt; this.start(); } public void run(){ for(int ii = 0; ii < 6; ii++){ mt.push(mc[ii]); try{
一个线程(执行上下文)由三个主要部分组成: 一个虚拟CPU CPU执行的代码 代码操作的数据
代码可以由多个线程共享,它不依赖数据。如果 两个线程执行同一个类的实例的代码时,则它们 可以共享相同的代码。 类似地,数据可以由多个线程共享,而不依赖代 码。如果两个线程共享对一个公共对象的访问, 则它们可以共享相同的数据。 在Java编程中,虚拟处理机封装在Thread类的一 个实例里。构造线程时,定义其上下文的代码和 数据是由传递给它的构造函数的对象指定的。 Java线程分守护线程和用户线程,由创建时设置。
public class Test { public static void main(String[] args) { MyStack ms = new MyStack(); Producer p = new Producer(ms); Consumer c = new Consumer(ms); } }
sleep(1);
} catch(Exception e){} } }
}
public class Consumer extends Thread{ MyStack mt; public Consumer(MyStack mt){ this.mt = mt; this.start(); } public void run(){ for(int ii = 0; ii < 6; ii++){ System.out.println(ii + " : " +mt.pop()); } } }
一个Thread对象在它的生命周期中会处于各种不同的状态。
Java线程不一定是分时的,所有你必须确 保你的代码中的线程会不时地给另外一个 线程运行的机会。有三种方法可以做到这 一点:
sleep() yield() join()
实例分析 2
课堂练习
问题描述: 以2种方式编写一个线程,打印1到100.
3 线程状态和调度 在Java中,线程是抢占式的,而不是分时的 (一 个常见的错误是认为“抢占式”只不过是“分时” 的一种新奇的称呼而已) 。 抢占式调度模型是指可能有多个线程是可运行的, 但只有一个线程在实际运行。
死锁
两个线程相互等待对方占用的锁 死锁不能被监测也不可避免 死锁可以通过以下方法来避免
确定获取锁的次序 始终遵照这个次序 按照相反的次序释放锁
同步示例
对前面的资源竞争的例子稍做改动。在 MyStack的两个方法进行同步。
public synchronized void push(char c){…} public synchronized char pop(){…}
实例分析 3
问题描述: 一个生产者(Producer)和一个消费者 (Consumer)分别从堆栈加入和取出字符
生产者向堆栈(MyStack)加入一个字符 消费者从同一个堆栈中取出一个字符
public class MyStack { int idx = 0; char [] data = new char[6]; public void push(char c) { data[idx] = c; idx++; } public char pop() { idx--; return data[idx]; } }
public void run() { while (true) { System.out.println("Hello " + i++); if (i == 50) break; } }
}
public class ThreadTest { public static void main(String args[]) { Xyz r = new Xyz(); Thread t = new Thread(r); t.start(); } } 一个新创建的线程并不自动开始运行.你必须调用它的start() 方法。例如,你可以发现上例中第4行代码中的命令: t.start(); 调用start()方法使线程所代表的虚拟处理机处于可运行状 态,这意味着它可以由JVM调度并执行。这并不意味着线程 就会立即运行。
通过wait()和notify()/notifyAll()方法进行同步 Object类中提供了用于线程通信的方法:wait()和 notify(),notifyAll()。如果线程对一个指定的对象 x发出一个wait()调用,该线程会暂停执行,此外, 调用wait()的线程自动释放对象的锁,直到另一个 线程对同一个指定的对象x发出一个notify()调用。 为了让线程对一个对象调用wait()或notify(),线程 必须锁定那个特定的对象。也就是说,只能在它 们被调用的实例的同步块内使用wait()和notify()。