收藏 分享(赏)

第10章 多线程机制.ppt

上传人:gnk289057 文档编号:9227027 上传时间:2019-07-30 格式:PPT 页数:42 大小:993.50KB
下载 相关 举报
第10章   多线程机制.ppt_第1页
第1页 / 共42页
第10章   多线程机制.ppt_第2页
第2页 / 共42页
第10章   多线程机制.ppt_第3页
第3页 / 共42页
第10章   多线程机制.ppt_第4页
第4页 / 共42页
第10章   多线程机制.ppt_第5页
第5页 / 共42页
点击查看更多>>
资源描述

1、第十章 多线程机制,本章的任务:理解Java的多线程机制,编写多线程程序。,本章主要内容:,1.多线程的概念2.创建线程3.线程的优先级4.线程的调度与控制,10.1 多线程的概念,为了理解线程的概念,先来了解程序、进程和多任务的概念。,10.1.1 程序、进程和多任务,程序(program)是对数据描述与操作的代码的集合,是应用程序执行的脚本。 进程(process)是程序的一次执行过程,是操作系统运行程序的基本单位。程序是静态的,进程是动态的。系统运行一个程序就是一个进程从创建、运行到消亡的过程。 多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每一个任务对应一个进程。

2、,10.1.2 线程,线程是比进程更小的运行单位,是程序中单个顺序的流控制。一个进程中可以包含多个线程。 线程是一种特殊的多任务方式。当一个程序执行多线程时,可以运行两个或更多的由同一个程序启动的任务。这样,一个程序可以使得多个活动任务同时发生。 线程与任何一个程序一样有一个开始、一系列可执行的命令序列、一个结束。在执行的任何时刻,只有一个执行点。线程与程序不同的是线程本身不能运行,它只能包含在程序中,只能在程序中执行。一个线程在程序运行时,必须争取到为自己分配的系统资源,如执行堆栈、程序计数器等等。,10.1.3 多线程,多线程是相对于单线程而言的,指的是在一个程序中可以定义多个线程并同时运

3、行它们,每个线程可以执行不同的任务。与进程不同的是,同类多线程共享一块内存空间和一组系统资源,所以,系统创建多线程花费单价较小。因此,也称线程为轻负荷进程。,10.1.4 线程的生命周期与Java的多线程机制,1线程的生命周期与状态 同进程一样,一个线程也有从创建、运行到消亡的过程,称为线程的生命周期。线程有创建(New)、可运行(Runnable)、运行中(Running)、挂起(Not Runnable)、死亡(Dead)五种状态。 2Java的多线程机制 java.lang中的线程类Thread封装了所有需要的线程操作控制,有很多方法用来控制一个线程的运行、休眠、挂起或停止。这就是Jav

4、a的多线程机制。,10.2 创建线程,如何编写一个带有多线程的程序呢? 一种方法是通过继承线程类Thread来创建线程类,; 另一个方法是建立一个实现Runnable接口的类来创建线程。,10.2.1 通过继承Thread类创建线程,例10.1 在程序中通过继承Thread类创建一个线程子类testThread,通过Thread1主类同时运行两个线程对象t1和t2。运行结果如图所示。,class Thread1 public static void main(String args) testThread t1=new testThread(“thread1“);testThread t2=n

5、ew testThread(“thread2“);t1.start();t2.start(); class testThread extends Thread public testThread(String str) super(str); / 调用父类的构造方法为线程对象命名,public void run() for (int i=0; i3; i+) System.out.println(getName()+“在运行“);try sleep(1000); / 用休眠1000毫秒来区分哪个线程在运行System.out.println(getName()+“在休眠“); catch (I

6、nterruptedException e) System.out.println(getName()+“已结束“); ,说明:,(1)Application应用程序运行时总是调用main方法 。 (2)从输出的结果可以看出两个线程的名字是交替显示的 。 (3)由继承Thread创建的子类,必须覆盖run方法,通过Thread类创建线程子类的格式为:,class 线程的类名 extends Thread public void run() 程序语句 ,10.2.2 通过Runnable接口创建线程,当一个类是从其他类继承时,如继承Applet类。此时就不能再继承Thread类来创建线程,这时可

7、以通过接口Runnable直接创建线程对象。接口Runnable是一个抽象接口,接口中只声明了一个未实现的run方法。,例10.2 通过Runnable接口运行线程。运行结果如图所示。,import java.awt.*; import java.applet.Applet; import java.util.*; import java.text.DateFormat;public class Clock2 extends Applet implements Runnable Thread clockThread=null;public void init() setBackground(C

8、olor.blue);setForeground(Color.yellow);,public void start() if (clockThread=null) clockThread=new Thread(this,“Clock2“);clockThread.start();public void run() Thread myThread=Thread.currentThread();while (clockThread=myThread) repaint();try Thread.sleep(1000);catch (InterruptedException e) ,public vo

9、id paint(Graphics g) Date date=new Date();DateFormat formatter=DateFormat.getTimeInstance();String str=formatter.format(date);g.drawString(str,5,10);public void stop() clockThread=null; ,说明1 :,(1)在Applet的start方法中用new操作符创建了一个线程对象clockThread:clockThread=new Thread(this,“Clock2“);clockThread.start(); (

10、2)在实现接口Runnable的run方法中,又通过Thread.currentThread方法创建了一个当前运行的线程对象myThread: Thread myThread=Thread.currentThread(); (3)设计Thread的run方法。,说明2:通过例10.2可以了解如何结束一个无限循环的线程。,一般设计线程自然结束。如例10.1通过定义循环次数自然结束线程。 在例10.2中,进入循环的条件是clockThread=myThread,怎样结束线程呢?当把这个Applet嵌入网页后,用户关闭这个网页时,Applet的stop方法将被调用:public void stop(

11、) clockThread=null;在这里clockThread被赋值null,破坏了循环条件,因此循环终止,结束线程。,两种创建线程方法的比较:,(1)由继承Thread类创建线程对象简单方便,可以直接操作线程,但不能再继承其他类。 (2)在继承其他类的类中可用Runnable接口创建线程对象。可保持程序风格的一致性。,10.3 线程的优先级,Java为了使有些线程可以提前得到服务,可给线程设置优先级。在单个CPU上运行多线程时采用了线程队列技术,Java虚拟机支持固定优先级队列,一个线程的执行顺序取决于它相对其它Runnable线程的优先级。,Thread定义了其中3个常数:,(1)MA

12、X_PRIORITY,最大优先级(值为10)。 (2)MIN_PRIORITY,最小优先级(值为1)。 (3)NORM_PRIORITY,缺省优先级(值为5)。,例10.3 线程优先级的使用。运行结果如图所示。,class Thread2 extends Thread public static void main(String args) Thread2 t=new Thread24;for(int i=0;i4;i+) ti=new Thread2();for(int i=0;i4;i+) ti.start();t1.setPriority(MIN_PRIORITY);t3.setPrio

13、rity(MAX_PRIORITY);public void run() for(int i=0; i1000000; i+);System.out.println(getName()+“线程的优先级是 “+getPriority()+“ 已计算完毕!“); ,10.4 线程的调度与控制,10.4.1线程类的方法 1.线程的类方法 以下是Thread类的静态方法,即可以直接从Thread类调用。 CurrentThread() 返回正在运行的Thread对象名称 sleep(int n) 让当前线程休眠n毫秒,2实例方法,activeCount() 返回该线程组中当前激活的线程的数目check

14、Access() 检测当前线程是否可以被修改destroy() 终止一个线程,不清除其他相关内容 getName() 返回线程的名称 getPriority() 返回线程的优先级 interrupt() 向一个线程发送一个中断信息 interrupted() 检查该线程是否被中断 isAlive() 检查线程是否处于激活状态 isDaemon() 检查该线程是否常驻内存 isInterrupted() 检查另一个线程是否被中断,10.4.2 控制线程的状态,1挂起一个线程 2停止一个线程 3线程休眠 4连接线程 5暂停线程 6中断线程 7了解线程的状态,10.5 线程的同步机制与共享资源,前面

15、的线程例子都是独立的,而且异步执行,也就是说每个线程都包含了运行时所需要的数据和方法,不需要外部资源,也不用关心其它线程的状态和行为。但有时一些同时运行的线程需要共享数据,例如两个线程同时存取一个数据流,其中一个对数据进行了修改,而另一个线程使用的仍是原来的数据,这就带来了数据不一致问题。因此,编程时必须考虑其它线程的状态和行为,以解决资源共享问题。 Java提供了同步设定功能。共享对象可将自己的成员方法定义为同步化(synchronized)方法,通过调用同步化方法来执行单一线程,其它线程则不能同时调用同一个对象的同步化方法。,例10.4 生产者和消费者线程同步化问题。使用某种资源的线程称为

16、消费者,产生或释放这个资源的线程称为生产者。生产者生成10个整数(09),存储到一个共享对象中,并把它们打印出来。每生成一个数就随机休眠0100毫秒,然后重复这个过程。一旦这10个数可以从共享对象中得到,消费者将尽可能快地消费这10个数,即把它们取出后打印出来。这个模型由4个程序组成。,1生产者程序,public class Producer extends Thread private Share shared;private int number;public Producer(Share s, int number) shared=s;this.number=number;,public

17、 void run() for (int i=0; i10; i+) shared.put(i);System.out.println(“生产者“+this.number+“ 输出的数据为:“+i);try sleep(int)(Math.random() * 100); catch (InterruptedException e) ,2消费者程序,public class Consumer extends Thread private Share shared;private int number;public Consumer(Share s, int number) shared=s;t

18、his.number=number;,public void run() int value = 0;for (int i=0; i10; i+) value=shared.get();System.out.println(“消费者“+this.number+“ 得到的数据为:“+value); ,3共享资源对象,public class Share private int contents;public int get()return contents;public void put(int value)contents=value; ,4主程序,public class PCTest pu

19、blic static void main(String args) Share s=new Share();Producer p=new Producer(s,1);Consumer c=new Consumer(s,1);p.start();c.start(); ,5改写后的程序对共享资源对象实现同步化,public class Share private int contents;private boolean available=false;public synchronized int get() while (available=false) try wait(); catch (

20、InterruptedException e) available=false;notifyAll();return contents;,public synchronized void put(int value) while (available=true) try wait(); catch (InterruptedException e) contents=value;available=true;notifyAll(); ,10.6 何时使用多线程及注意问题,当你考虑到多线程时,你立刻会想到某些任务是可以使用多线程,例如数据计算、数据库查询,以及输入的获得。因为这些任务通常都被认为是

21、后台任务,不直接与用户打交道。在这些任务中,你当然可以使用多线程。那么还有没有其他的任务也适合多线程呢?在Java语言程序设计中,动态效果的程序都会使用多线程,例如动画的播放、动态的字幕等等。,在程序中使用多线程对系统产生以下影响:,(1)线程需要占用内存。 (2)线程过多,会消耗大量CPU时间来跟踪线程。 (3)必须考虑多线程同时访问共享资源的问题,如果没有协调好,就会产生令人意想不到的问题,例如可怕的死锁和资源竞争。 (4)因为同一个任务的所有线程都共享相同的地址空间,并共享任务的全局变量,所以程序也必须考虑多线程同时访问全局变量的问题。,习 题,1.Java语言中的线程和多线程指的是什么

22、? 2.用继承的方法创建一个多线程程序。 3.使用接口Runnable创建一个多线程程序。 4.同步机制有什么作用? 5.能否在生产者和消费者模型中使用synchronized关键词锁定资源对象达到同步的目的,请你重写程序,并在机上进行试验。,6.下面有关线程的哪些叙述是对的。 A. 一旦一个线程被创建,它就立即开始运行。 B.使用start()方法可以使一个线程成为可运行的,但是它不一定立即开始运行。 C.当一个线程因为抢先机制而停止运行,它被放在可运行队列的前面。 D.一个线程可能因为不同的原因停止运行并进入就绪状态。 7.方法resume()负责恢复哪些线程的执行? A. 通过调用stop()方法而停止的线程。 B.通过调用sleep()方法而停止运行的线程。 C.通过调用wait()方法而停止运行的线程。 D.通过调用suspend()方法而停止运行的线程。,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报