多线程46幻灯片课件

上传人:bin****86 文档编号:55037763 上传时间:2018-09-23 格式:PPT 页数:41 大小:519KB
返回 下载 相关 举报
多线程46幻灯片课件_第1页
第1页 / 共41页
多线程46幻灯片课件_第2页
第2页 / 共41页
多线程46幻灯片课件_第3页
第3页 / 共41页
多线程46幻灯片课件_第4页
第4页 / 共41页
多线程46幻灯片课件_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《多线程46幻灯片课件》由会员分享,可在线阅读,更多相关《多线程46幻灯片课件(41页珍藏版)》请在金锄头文库上搜索。

1、java多线程,学习目标,线程的基本概念 线程的创建和启动 线程的调度和优先级 线程的状态控制 线程同步,多任务,多任务-在同一时刻似乎有多个程序(进程)在同时运行的能力 多任务管理的实现方法- 抢占式多任务-直接中断而不需要事先和被中断程序协商(UNIX/Linux,Windows NT/XP) 协作式多任务-只有在被中断程序同意交出控制权之后才能执行中断(windows3.x和Mac OS 9和手机) 正是由于这种多任务操作系统的出现才有了多线程这个概念,线程概述,每个进程都有独立的代码和数据空间,进程切换到开销大。 线程:轻量的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和

2、程序计数器(标识该线程代码运行到那个地方),线程切换的开销小 多进程:在多任务操作系统中能(同时)运行多个任务(程序) 多线程:在同一应用程序中有多个顺序流(多个顺序流被称为多线程)(同时)执行 注意:同时是指同一个时间段,是因为cpu把时间段分成很多个时间片,同一个时间片运行不同的进程或线程,再因为cpu运行的速度相当的快,所以我们感觉他们是在同一时间内完成多个事情 每一个进程分配一块内存空间,每一个进程的多个线程共用同一个内存,线程的创建和启动,创建线程有两种方式: 继承java.lang.Thread类 实现java.lang.Runnable接口,继承java.lang.Thread类

3、,Thread类代表线程类,它的最主要的两个方法是: run()-包含线程运行时所要执行的代码,称为线程体,是线程启动的入口 start()-用于启动线程 说明:用户定义的线程类只需要继承Thread类,覆盖Thread类的run()方法,最后使用start()就可以启动用户定义的线程了,Java线程模型,虚拟的CPU,由java.lang.Thread类封装和虚拟CPU来实现。 CPU所执行的代码,传递给Thread类对象。 CPU所处理的数据,传递给Thread类对象。,代 码,数 据,虚拟CPU,Java线程模型,线程例子,public class ThreadDemo1 extends

4、 Thread /* param args*/ public static void main(String args) /子线程1 ThreadDemo1 t1 = new ThreadDemo1(); /设置线程 t1.setName(“线程1“); /启动线程 t1.start(); /子线程2 ThreadDemo1 t2 = new ThreadDemo1(); t2.setName(“线程2“); t2.start();/主线程调用 for (int i = 0; i 50; i+) System.out.println(Thread.currentThread().getName

5、() + “=-“ + i); public void run() for (int i = 0; i 50; i+) /得到启动线程的名字 System.out.println(Thread.currentThread().getName() + “=“ + i); ,启动线程,每个线程都是通过某个特定Thread对象所对应的方法run( )来完成其操作的,方法run( )称为线程体。 使用start()方法,线程进入Runnable(可运行)状态,它将向线程调度器注册这个线程。 调用start()方法并不一定马上会执行这个线程,正如上面所说,它只是进入Runnable 而不是Running

6、。 注意,不要直接在程序中调用线程的run()方法。 run()方法会被线程自动调用,Thread注意,ThreadDemo1 t1 = new ThreadDemo1(); t1.start(); t1.start();/报java.lang.IllegalThreadStateException异常 一个线程只能启动一次,Runnable创建线程的另一种方式,通过实现Runnable接口并实现接口中定义的唯一方法run(),可以创建一个线程,如果要想启动该线程就必须将实现Runnable接口的实现类对象传递到Thread对象中,再通过Thread中的start()方法来启动,用Runnab

7、le创建线程的例子,public class RunnableThread implements Runnable /实现接口Runnable中的run方法public void run()for (int k = 0;k10;k+)System.out.println(“Count:“+k); ,多线程共享代码和数据,多线程之间可以共享代码和数据 用例题解释,得到当前线程对象的引用,Thread类的currentThread()静态方法返回当前线程对象的引用,两种线程创建方式的比较,使用Runnable接口 还可以从其他类继承; 保持程序风格的一致性。 直接继承Thread类 不能再从其他类

8、继承; 编写简单,可以直接操纵线程,例如(this.getName()) 是因为Thread类实现了Runnable接口,结束线程,线程会以以下三种方式之一结束: 线程到达其 run() 方法的末尾; 线程抛出一个未捕获到的 Exception 或 Error; 另一个线程调用一个过时的危险的 stop() 方法(stop方法已经过期)。,线程状态,就绪状态,运行状态,阻塞状态,新建状态,start(),run() 运行完毕,线程调度器,导致阻塞的事件,解除阻塞,消亡,线程状态,新建状态:使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new t

9、hread)(不调用start()方法新创建的线程不会被启动) 就绪状态:使用start()方法启动一个线程后,系统为该线程分配了除CPU外的所需资源,使该线程处于可运行状态(Runnable) 运行状态:java运行系统通过调度选中一个可运行状态的线程,使其占有CPU并转为运行中状态(Running)或者运行一定时间后进入就绪状态重新等待线程调度器来调度执行.此时,系统真正执行线程的run()方法.,线程状态,阻塞状态:一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态(Blocked) 消亡:线程结束后是死亡状态(Dead),明确让出线程的方式,调整各个线程的优先级,但是cpu不一定

10、会按照线程的优先级来运行,只是优先级高的的到运行的机会多 让处于运行状态的线程调用另一个线程的join()方法 让处于运行状态的线程调用Thread.sleep(毫秒)方法 让处于运行状态的线程调用Thread. yield()方法,线程的优先级,所有处于就序状态的线程根据优先级存放在可运行区,优先级高的线程获得较多的运行机会,不是优先级高的先执行完毕 Thread类的setPriority(int)和getPriority()方法分别用来设置优先级和读取优先级,优先级用整数表示,取值范围是1到10,Thread类有以下3个优先级常量值 主线程的默认优先级为5,由主线程创建的子线程的默认优先级

11、和主线程的优先级相等 MAX_PRIORITY 取值为10,表示最高优先级 MIN_PRIORITY 取值为1,表示最低优先级 NORM_PRIORITY 取值为5,表示默认优先级 注意:根据我多次测试,不是一定设置了最高优先级就一定会先执行完,只是被运行的机会多 用法举例:PriorityDemo.java,线程串行化join,当前运行的线程可以调用类的当前运行的线程的join() 方法,另一个运行的线程将转到阻塞状态,直至当前线程运行结束,另一线程才会恢复运行 Join相关方法介绍 join()等待该线程终止。 join(long millis) 等待该线程终止的时间最长为 millis

12、毫秒。 join(long millis, int nanos)等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 Join()方法会抛出InterruptedException异常,如果另一个线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除 用法举例: JoinDemo1.java 演示线程串行化 JoinDemo2.java 演示线程串行化实现文件先写再读到操作,线程休眠sleep,当一个线程在运行中执行了sleep()方法时,它就会放弃CPU,转到阻塞状态,等待指定的“延迟时间”到了就讲线程转入到就绪状态 相关方法介绍: sleep(long milli

13、s) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。 sleep(long millis, int nanos)在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)。 用法举例: SleepDemo1.java SleepDemo2.java使用sleep方法来显示时钟,线程让步yield,当线程在运行中执行了Thread类的yield()静态方法,如果此时具有相同优先级的其他线程处于就绪状态,那么yield()方法将把当前运行的线程放到可运行池中并使另一个线程运行。如果没有相同优先级和比该线程优先级高的,则yield()方法有可能什么都不做,但是不是一定的 相关方法介绍

14、 yield() 暂停当前正在执行的线程对象,并执行其他线程。 用法举例: YieldDemo.java,sleep和yield,Sleep()方法会给其他线程运行的机会,而不考虑其他线程的优先级,因此会给较低优先级线程一个运行的机会;yield()方法只会给相同优先级和更高优先级的线程一个运行的机会,不是一个绝对的 当线程执行了sleep(long millis)方法后,将转到阻塞状态,参数millis指定睡眠的时间,再转到就绪状态;当线程执行了yield()方法后,将转到就绪状态 Sleep() 方法声明抛出InterruptedException异常,而yield()方法没有声明抛出任何

15、异常 Sleep()方法比yield()方法具有更好的可移植性。不能依靠yield()方法来提高程序的并发性能。对于大多数程序员来说,yield()方法的唯一用途是在测试期间人为地提高程序的并发性能,以帮助发现一些隐藏的错误,后台线程,有一种线程,它是在后台运行的,它的任务是为其他的线程提供服务,这种线程被称为“后台线程(Daemon Thread)”,又称为“守护线程“(Java的垃圾回收机制就是一个后台线程,回收其他不再使用的内存),后台线程的特点,后台线程与前台线程相伴相随,只有所有前台线程都结束生命周期,后台线程才会结束生命周期。只要有一个前台线程还没有运行结束,后台线程就不会结束生命

16、周期 主线程在默认情况下是前台线程,由前台线程创建的线程默认情况下也是前台线程。调用Thread类的setDaemon(true)方法,就能把一个线程设置为后台线程。Thread类的isDaemon()方法用于判断一个线程是否是后台线程,后台线程常用方法介绍,isDaemon()测试该线程是否为后台线程 setDaemon(boolean on)将该线程标记为后台线程或用户线程 注意:主线程不可以作为后台线程 用法举例:DaemonDemo.java,与线程控制有关的方法,多线程共享,多线程共享数据时的问题,经典的银行取款问题 有一个银行账户,还有余额1100元,现在A通过银行卡从中取1000

17、元,而同时另外一个人B通过存折也从这个账户中取1000元。取钱之前,要首先进行判断:如果账户中的余额大于要取的金额,则可以执行取款操作,否则,将拒绝取款。 我们假定有两个线程来分别从银行卡和存折进行取款操作,当A线程执行完判断语句后,获得了当前账户中的余额数(1000元),因为余额大于取款金额,所以准备执行取钱操作(从账户中减去1000元),但此时它被线程B打断,然后,线程B根据余额,从中取出1000元,然后,将账户里面的余额减去1000元,然后,返回执行线程A的动作,这个线程将从上次中断的地方开始执行:也就是说,它将不再判断账户中的余额,而是直接将上次中断之前获得的余额减去1000。此时,经过两次的取款操作,账户中的余额为100元,从账面上来看,银行支出了1000元,但实际上,银行支出了2000元。,

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > PPT模板库 > 其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号