第13章龟兔赛跑——多线程.ppt

上传人:本田雅阁 文档编号:2251076 上传时间:2019-03-11 格式:PPT 页数:25 大小:234.01KB
返回 下载 相关 举报
第13章龟兔赛跑——多线程.ppt_第1页
第1页 / 共25页
第13章龟兔赛跑——多线程.ppt_第2页
第2页 / 共25页
第13章龟兔赛跑——多线程.ppt_第3页
第3页 / 共25页
亲,该文档总共25页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《第13章龟兔赛跑——多线程.ppt》由会员分享,可在线阅读,更多相关《第13章龟兔赛跑——多线程.ppt(25页珍藏版)》请在三一文库上搜索。

1、第13章 龟兔赛跑多线程,能力目标: 理解多线程、掌握线程的创建、启动、运行等方法。 掌握线程优先级及其设置方法。 理解线程状态,线程中断和线程同步等概念。 能使用多线程编写龟兔赛跑程序和生产者消费者程序。,内容介绍,13.1 任务预览 13.2 程序、进程与线程 13.3 多线程 13.4 线程类Thread 13.5 线程同步与互斥 13.6 本章小结 13.7 实训13:龟兔赛跑、生产者与消费者,13.1 任务预览,本章实训程序运行结果:,13.2 程序、进程与线程,程序,是代码,是静态的。 进程,是程序在计算机上的一次运行过程,进程是动态的。 线程也是动态的,是比进程更小的概念,它是进

2、程(程序运行过程)的一条执行路线。 Java语言拥有多线程机制。 java.lang包提供线程类Thread,只要定义继承Thread类的子类,并重写线程运行方法run。 线程类的每一个对象都是一个线程,通过start方法启动。,【例13-1】编写龟兔赛跑多线程程序,设赛跑长度为100米,每跑完10米输出一次结果。,class Animal extends Thread /线程类 public Animal(String name) /构造方法,参数是线程名 super(name); public void run() /线程运行方法 for(int i=0; i=100; i+=10) if

3、 (this.getName().equals(“乌龟“) System.out.println(“tt乌龟跑了“+ i + “米“); else System.out.println(this.getName() + “跑了“+ i + “米“); try Thread.sleep(long)(Math.random()*1000); /休眠不超过1秒 catch(InterruptedException e) ,续例13-1,public class Example1 /运行主类 public static void main(String args) Animal rabbit = ne

4、w Animal(“兔子“); /线程(对象)1 Animal tortoise = new Animal(“乌龟“); /线程(对象)2 rabbit.start(); /启动线程1 tortoise.start(); /启动线程2 ,13.3 多线程 13.3.1 构建Thread子类对象,(1)编写Thread子类,即线程类,格式: class 线程类名称 extends Thread . public void run() . /线程运行方法 如: class Animal extends Thread . (2)构建线程对象。如: Animal rabbit = new Animal

5、(“兔子“); /线程(对象)1 Animal tortoise = new Animal(“乌龟“); /线程(对象)2 (3)调用线程对象的start方法启动线程。如: rabbit.start(); /启动线程1 tortoise.start(); /启动线程2 注:主类main方法也是一条独立的执行路线(线程)。,13.3.2 用实现Runnable接口的对象构建Thread对象,(1)编写实现Runnable接口的类,格式: class 类名 extends 父类implements Runnable . public void run() . /线程运行方法 (2)构建实现Runn

6、able接口类的对象。如: new Animal2(“兔子“) new Animal2(“乌龟“) (3)使用上述对象作参数,构造Thread对象。如: Thread rabbit = new Thread(new Animal2(“兔子“); Thread tortoise = new Thread(new Animal2(“乌龟 (4)最后调用start方法启动线程。,【例13-2】采用实现Runnable接口的方法编写龟兔赛跑多线程程序,功能与例13-1完全一样。,class Animal2 implements Runnable private String name; public

7、Animal2(String name) this.name = name; public String getName() return name; public void run() /线程运行方法 for(int i=0; i=100; i+=10) if (this.getName().equals(“乌龟“) System.out.println(“tt乌龟跑了“+ i + “米“); else System.out.println(this.getName() + “跑了“+ i + “米“); try Thread.sleep(long)(Math.random()*1000);

8、 catch(InterruptedException e) Thread rabbit = new Thread(new Animal2(“兔子“); Thread tortoise = new Thread(new Animal2(“乌龟“); rabbit.start(); tortoise.start(); ,13.4 线程类Thread 13.4.1 Thread类构造方法及线程名称,Thread类的类头声明: public class Thread extends Object implements Runnable 每个线程对象都有名称,如果没有在构造方法中指定,则按“Threa

9、d-”+ n的形式自动命名,也可用setName(String name) 方法设定。 常用构造方法: (1)Thread()。自动起名,用方法getName()获取线程名。 (2)Thread(String name):要指定线程名作参数。 (3)Thread(Runnable target):也是自动起名。 (4)Thread(Runnable target, String name)。,13.4.2 线程优先级与Thread相关字段,线程有10个优先级,从高至低分别是10、9、1。中间级为5,它是线程默认的优先级。 Thread类有3个关于优先级的整型静态常量字段: (1)MAX_PRI

10、ORITY:最大优先级,值是10。 (2)MIN_PRIORITY:最小优先级,值是1。 (3)NORM_PRIORITY,普通优先级,值是5。 方法setPriority(int newPriority)用于设置线程优先级, 方法getPriority()用于获取线程优先级。,【例13-3】改进例13-1的龟兔赛跑程序,通过改变优先级,并减掉休眠时间,使得乌龟以迅雷不及掩耳的速度跑完100米。,class Animal3 extends Thread public Animal3(String name) super(name); public void run() for(int i=0;

11、 i=100; i+=10) if (this.getName().equals(“乌龟“) (“tt乌龟跑了“+ i + “米“); else (this.getName() + “跑了“+ i + “米“); Animal3 rabbit = new Animal3(“兔子“); rabbit.setPriority(Thread.MIN_PRIORITY); Animal3 tortoise = new Animal3(“乌龟“); tortoise.setPriority(Thread.MAX_PRIORITY); rabbit.start(); tortoise.start(); ,

12、13.4.3 线程生命周期与线程状态,线程生存期间,存在6种状态: (1)NEW:新建状态。 (2)RUNNABLE:运行状态, (3)BLOCKED:阻塞状态, (4)WAITING:等待状态, (5)TIMED_WAITING:定时等待状态, (6)TERMINATED:终止(死亡)状态, 它们都是枚举常量,定义在Thread类嵌套枚举类型State。 线程新建状态就表示为Thread.State.NEW, 线程运行状态表示为Thread.State. RUNNABLE,等。 线程运行过程中状态通过调用getState方法来获取。 注:阻塞、等待和定时等待这3种可归纳为暂停状态,因此线程的

13、状态又划分为新建、运行、暂停和死亡这4种状态。此外,线程还有一种称为“就绪”的状态,万事俱备,只欠CPU。为简单起见,就绪状态被纳入到运行状态中。 线程是有生命,还可通过执行线程方法isAlive来判断。,13.4.4 线程其它方法,(1)currentThread:静态的获取当前正在执行线程对象引用方法。 (2)sleep:静态线程休眠方法。调用休眠方法必须处理中断异常。 (3)interrupt:中断(中途打断)线程方法。 (4)activeCount:静态的当前活动线程数方法 来自根类Object的与线程有关方法: Wait:等待方法。 Notify:通知方法,这两个方法配套使用。 no

14、tifyAll:通知所有等待线程方法。,【例13-4】编写兔子休眠后被乌龟中断(吵醒)的多线程程序。,class Animal4 implements Runnable Thread rabbit, tortoise; public Animal4() rabbit = new Thread(this,“兔子“); tortoise = new Thread(this, “乌龟“); public void run() /线程运行方法 if(Thread.currentThread() = rabbit) try System.out.println(“兔子正在睡大觉.“); rabbit.s

15、leep(1000*60*2); /兔子休眠2小时 catch(InterruptedException e) System.out.println(“兔子被叫醒“); System.out.println(“兔子开始跑步.“); else if(Thread.currentThread() = tortoise) System.out.println(“乌龟大叫:跑步去!“); rabbit.interrupt(); /中断(吵醒)兔子线程 System.out.println(“乌龟开始跑步.“); ,续13-4, Thread mainThread=Thread.currentThrea

16、d(); String name = mainThread.getName(); (“程序刚开始运行时的线程名:“ + name); (name + “ 线程状态:“ + mainThread.getState(); (“当前活动线程数:“ + Thread.activeCount(); Animal4 animal = new Animal4(); (“兔子线程状态:“ + animal.rabbit.getState(); (“乌龟线程状态:“ + animal.tortoise.getState(); animal.rabbit.start(); (“兔子线程状态:“ + animal.

17、rabbit.getState(); animal.tortoise.start(); (“乌龟线程状态:“ + animal.tortoise.getState(); (“当前活动线程数:“ + Thread.activeCount(); ,13.5 线程同步与互斥 13.5.1 同步关键字synchronized,临界资源:在某一时刻只能独占使用(互斥)、在不同时刻又允许多人共享的资源。例子: 公司的银行账户,由公司授权多人存、取钱,但每次只允许一个人存取。 手机等产品,先由生产者生产,后才卖给消费者,一个产品不能同时处于生产和消费中。 线程的同步和互斥:处理临界资源,涉及多线程之间相互协

18、作(步骤协调)。 synchronized修饰的方法,犹如对临界资源加“锁”,令方法执行过程对临界资源进行“同步”(协同好步骤)操作。 synchronized还可直接锁定一个临界资源,语法: synchronized( 临界资源对象 ) 操作代码 ,【例13-5】编写对银行账户临界资源的进行同步操作的多线程程序。,class Account /银行账户(临界资源)类 private String name; /账户名称 private double balance; /账户余额 public Account(String name, double money) this.name = nam

19、e; balance = money; public synchronized void deposit(double money) /同步存款 if (money0) balance += money; notify(); println(“成功存款¥“+ money + “,余额¥“ + balance); else System.out.println(“存款失败“); public synchronized void withdraw(double money) /同步取款 if (money0) while (moneybalance) try wait(); catch(Inter

20、ruptedException e) balance -= money; println(“成功取款¥“+ money + “,余额¥“ + balance); else System.out.println(“取款失败“); public double getBalance() return balance; public String getName() return name; ,续例13-5,class DepositThread extends Thread Account acc; /存款线程类 public DepositThread(Account a) acc = a; pu

21、blic void run() for(int i=0; i5; i+) /存款5次 acc.deposit(int)(Math.random()*1000); /每次1000 class WithdrawThread extends Thread /取款线程类 Account acc; public WithdrawThread(Account a) acc = a; public void run() for(int i=0; i5; i+) /取款5次 acc.withdraw(int)(Math.random()*1000);/每次1000 Account a1 = new Accou

22、nt(“光明公司“, 5000); /开户 println(a1.getName() + “银行账户余额¥“ + a1.getBalance(); WithdrawThread withdrawMan = new WithdrawThread(a1); DepositThread depositMan = new DepositThread(a1); withdrawMan.start(); depositMan.start(); ,13.5.2 生产者与消费者模型,(1)有一个具有一定容量的存放产品的仓库。 (2)生产者不断生产产品,产品保存在仓库中(产品入仓)。 (3)消费者不断购买仓库中

23、的产品(产品出仓)。 (4)只有仓库有空间,生产者才能生产,否则只能等待。 (5)只有仓库存在产品,消费者才能购买(消费)。 在生产者与消费者模型中,涉及4个概念:产品、仓库、生产者和消费者,关键是后3个: (1)仓库,是临界资源,仓库的产品不能同时入仓和出仓。 (2)生产者线程:工人。 (3)消费者线程:购买产品的人。 现实世界中,许多问题都可归结为生产者与消费者模型,比如公司银行账户的存取款操作,银行账户相当于一个海量仓库,生产(存款)能力没有限制。,【例13-6】编写生产与消费多线程程序,设有最大库存量3的库,生产10台洗衣机并消费掉。,class Storage /仓库类 privat

24、e String name; /产品名称 private int max; private int num; /最大库存量、产品库存数 private int serialNum; /产品编号(入仓号) public Storage(String name, int max) public synchronized void input() /同步的生产(入仓)方法 while (num = max) /若产品数超出最大库存量 try wait(); catch(Exception e) /则等待 this.num +; /直到被通知唤醒才生产 serialNum +; notify(); /

25、通知消费 (“生产编号“+ serialNum + name + “,当前库存数:“+ num); public synchronized void output() /同步的消费(出仓)方法 while (num = 0) /若库存没有产品 try wait(); catch(Exception e) /则等待 this.num -; /直到被通知唤醒才消费 notify(); /通知生产 (“消费编号“+ name+“,当前库存数:“+num); ,续13-6,class Producer extends Thread /生产者类 Storage store; public Produce

26、r(Storage store) this.store = store; public void run() for(int i=0; i10; i+) store.input(); /调用同步生产方法 class Consumer extends Thread /消费者类 Storage store; public Consumer(Storage store) this.store = store; public void run() for(int i=0; i10; i+) store.output(); /调用同步消费方法 Storage store = new Storage(“洗

27、衣机“, 3); /库存3洗衣机仓库 Producer producer = new Producer(store); /生产者 Consumer consumer = new Consumer(store); /消费者 producer.start(); consumer.start();,13.6 本章小结,线程是比进程更小的概念。 编写多线程程序涉及到线程类Thread。 编写多线程程序有两种方式:一是编写Thread子类并构造其对象,二是编写实现Runnable接口的类,再用该类对象作参数构造Thread对象。 线程的执行路线通过run方法实现。 线程按其重要程度分成10个优先级,缺省

28、是5。 线程的状态可概括为4种:新建、运行、暂停(阻塞及等待)、死亡。 多线程并发执行,涉及共享的临界资源冲突问题。如公司账户,工厂产品等,宏观上同时被多个线程使用,但微观上在某一时刻只能被一个线程独占使用。 线程同步与互斥最典型的应用是生产者与消费者模型。 编写该模型的多线程,要使用关键字synchronized。,13.7 实训13:龟兔赛跑、 生产者与消费者,(1)编写龟兔赛跑多线程程序,设赛跑长度为100米,赛跑过程中,每跑完10米输出一次结果。每次运行结果不尽相同,有时乌龟快,有时兔子快。 (2)编写生产者消费者多线程程序,设有一个最大库存量为4的电视机仓库,生产10台电视机,一边生产一边销售(消费)。,谢谢! 返回目录 结束放映,

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1