Java-核心标称技术图文课件--13.pptx
《Java-核心标称技术图文课件--13.pptx》由会员分享,可在线阅读,更多相关《Java-核心标称技术图文课件--13.pptx(74页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、 1%大连理工大学出版社地址:大连市软件园路80号发行:0411-84708842E-mail:DutpD(第二版)主编:张屹蔡木生新世纪应用型高等教育软件专业系列规划教材Java Java Java Java 核心编程技术核心编程技术核心编程技术核心编程技术 2 绩效概述绩效管理绩效管理实施过程KPI与BSc第 2 页第13章 多线程与网络编程13.2创建线程的方式13.1线程的概念13.3线程的生命周期13.5多线程的应用13.4线程同步 目 录 13.6网络编程的基本概念13.8UDP编程13.7TCP编程 3 第十三章 多线程与网络编程13.1线程的概念对于初学者来说,线程概念很抽象。
2、首先,我们来观察两个简单的程序例13.1和例13.2,一个是普通的顺序执行程序,另一个是使用线程的程序。4 第十三章 多线程与网络编程13.1线程的概念对于初学者来说,线程概念很抽象。首先,我们来观察两个简单的程序例13.1和例13.2,一个是普通的顺序执行程序,另一个是使用线程的程序。5 第十三章 多线程与网络编程13.1线程的概念 6 第十三章 多线程与网络编程13.1线程的概念虽然例13.1显示的结果与例13.2所显示的结果一样,都对访问A和访问B显示五次。但运行时我们发现,例13.2的运行时间几乎只有例13.1的一半。这是为什么呢?通过对程序的分析,得知在例13.1中,先执行序列A五次
3、后才执行序列B,而例13.2则在执行线程A休眠时,线程B使用了CPU,从而节省运行时间,提高运行效率。下面,我们来具体认识线程。7 第十三章 多线程与网络编程13.1线程的概念对于学过操作系统的读者来说,都知道进程(Process)就是程序运行时的一个实例。线程(Thread)和进程相似,都是独立的线性控制流。但线程是在进程提供的环境下执行的,线程只是程序中的一个单独的控制流,而并非程序,因为不能依靠自身单独运行,必须依赖程序,在程序中执行。因此,线程是比进程更小的单元,线程是一组指令的集合,或者是程序的特殊段,它可以在程序中独立执行。所以线程基本上是轻量级的进程,它和进程一样拥有独立的执行控
4、制,由操作系统负责调度。13.1.1什么是什么是线程程 8 第十三章 多线程与网络编程13.1线程的概念多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立,又共同协作。通常由操作系统负责多个线程的调度和执行。使用多线程是为了使多个线程并行地工作以完成多项任务,以提高系统的效率。可以说,多线程是多任务的特殊形式。一个程序可以有多个线程,各个线程看上去像是并行地独自完成各自的工作,就像一台计算机上运行着多个处理机一样。在多处理机上实现多线程时,它们确实可以并行工作,而且采用适当的分时策略可以大大提高程序运行的效率。但是二者还是有较大的不同的,线程是共享
5、地址空间的,也就是说多线程可以同时读取相同的地址空间,并且利用这个空间进行数据交换(这可能带来数据冲突的问题,这也是本章的主要内容之一),而处理机则不共享空间。13.1.2什么是多什么是多线程程 9 第十三章 多线程与网络编程13.1线程的概念使用多线程有什么优点呢?首先我们来看几个有关多线程的例子。比如,一个服务器程序可以同时为多个客户端提供服务;一个浏览器可以同时浏览多个页面等,都属于使用线程的现象。因此在我们接触的程序中,使用多线程的情况非常多。多线程的优点大致有以下三个方面:.加快程序的运行速度。.使用GUI界面设计,使用户界面更加吸引人。例如,用户单击了一个按钮去触发某些事件的处理,
6、可以弹出一个进度条来显示处理的进度等。.在一些等待的任务的实现上可以使用线程。例如,用户输入、文件读写和网络收发数据等,在这种情况下我们可以释放一些资源,如内存占用、CPU占用等。13.1.3多多线程的程的优点点 10 第十三章 多线程与网络编程13.2创建线程的方式13.2.1继承承Thread类创建建线程程Thread类提供了创建、运行和控制线程的相关方法,我们将会在后面的小节中逐步介绍它们的作用。通过继承Thread类,并重写其中的run()方法来定义线程体,以实现线程的具体行为,然后创建该子类的对象以创建、启动线程。其具体编程步骤为:11 第十三章 多线程与网络编程13.2创建线程的方
7、式13.2.1继承承Thread类创建建线程程Thread类提供了创建、运行和控制线程的相关方法,我们将会在后面的小节中逐步介绍它们的作用。通过继承Thread类,并重写其中的run()方法来定义线程体,以实现线程的具体行为,然后创建该子类的对象以创建、启动线程。其具体编程步骤为:12 第十三章 多线程与网络编程13.2创建线程的方式13.2.1继承承Thread类创建建线程程 13 第十三章 多线程与网络编程13.2创建线程的方式13.2.1继承承Thread类创建建线程程 14 第十三章 多线程与网络编程13.2创建线程的方式13.2.1继承承Thread类创建建线程程下面对例13.3的代
8、码进行详细说明:(1)程序运行时总是调用main()方法,因此main()是创建和启动线程的地方。MultiThreadExample1的main()方法中生成了三个MyThread1线程对象,并调用start()方法启动这三个线程。(2)从例13.3的运行结果可以看出,三个线程的名字是无规则显示的,这是因为三个线程是同步的,于是,三个run()方法也同时被执行。每一个线程运行到输出语句时将在屏幕上显 示自己的名字,执行到sleep语句时将休眠01000毫秒中的一个随机值。线程休眠时并不 占用CPU,其他线程可以继续执行。一旦休眠达到设定的时间长度,线程将被唤醒,继续执行下面的语句。这样,就实
9、现了交替显示。15 第十三章 多线程与网络编程13.2创建线程的方式13.2.1继承承Thread类创建建线程程(3)Thread类创建的线程不做任何事情,因为它的run()方法是空的。所以,对于继承自 Thread的子类来说,务必要覆盖run()方法。run()是Thread类的关键方法,线程的所有活动 都是通过它来实现的。当线程实例化后系统就调用run()方法,正是通过run()方法才使创建 线程的目的得以实现。我们可以在run()方法里控制程序,一旦进人run()方法,便可执行里 面的任何语句,run()方法执行完毕,这个线程也就结束了。16 第十三章 多线程与网络编程13.2创建线程的
10、方式13.2.2实现Runnable接口接口创建建线程程任何类都可以实现Runnable接口,而这个类的实例将用一个线程来调用,以启动这个类的run()方法。Runnable接口的run()方法,其作用和Thread类的run()方法相同。其具体 的编程步骤如下:17 第十三章 多线程与网络编程13.2创建线程的方式13.2.2实现Runnable接口接口创建建线程程 18 第十三章 多线程与网络编程13.2创建线程的方式13.2.2实现Runnable接口接口创建建线程程 19 第十三章 多线程与网络编程13.2创建线程的方式13.2.3两种两种创建建线程方式的比程方式的比较Thread类是
11、Java已经严格封装好的类,在面向对象思想中,继承这样的类并修改或扩充它并不是十分可取的。因为可能会出现人为失误,对一个类进行继承修改或扩充,将可能导致该子类出现不可预料的错误。另外,由于Java不支持多重继承,一个继承了 Thread的类将无法再继承其他类,因此在 某些情况下只能采用实现Runnable接口的方式,例如要实现多线程的Applet则必须通过实 现Runnable接口创建线程。实现Runnable接口方式的缺点在于,在run()方法中如果要调用当前线程自身的方法,必须先通过调用Thread.currentThread()以获得对当前线程自身的引用,而采用继承Thread 类方式时
12、,可以直接调用当前线程自身的方法。后者为代码的编写带来了 一定的便利,但这点 便利与上述可能造成的不可预料的错误相比,不具有太大的意义。因此如果没有绝对的把握 保证继承Thread类的子类的正确性和完整性,建议采用实现Runnable接口的方式创建 线程。20 第十三章 多线程与网络编程13.2创建线程的方式13.2.3两种两种创建建线程方式的比程方式的比较然而,实现Runnable接口的方式并不一定总是最好的,例如要获得拥有特殊功能的线程必须通过继承并扩充Thread接口实现,此时若对Thread类的修改或扩充并不大,并希望保证其正确性和完整性,则更应该采用继承Thread类的方式。这也正是
13、本章多采用继承 Thread类的方式的原因。在实际应用中,应该根据实际情况,权衡两种方式带来的影响,选择最合适的方式。21 第十三章 多线程与网络编程13.3线程的生命周期13.3.1线程生命周期的状程生命周期的状态所谓线程的生命周期,是指线程从创建之初到运行完毕的整个过程,就像人的整个生命周期从出生,经历童年、少年、青年、中年、老年,直到去世一样。线程的整个生命周期就是在各种状态间切换的,其过程如图所示。线程的生命周期 22 第十三章 多线程与网络编程13.3线程的生命周期13.3.1线程生命周期的状程生命周期的状态下面介绍上图的各个状态。.新生(New):线程刚通过构造方法被创建时即处于此
14、状态,此时线程还没有启动,无法运行。.可运行(Runnable):线程位于一个等待池中,等待被调度到CPU 运行,此时线程已启动,并做好了一切运行的准备,随时可以占用CPU运行。.运行(Running):线程占用CPU运行。.死亡(Dead):线程运行结束,结束方式可以是run()方法正常结束,或从run()方法返回,或者产生没有捕捉的异常。.阻塞(Blocked):线程由于某种原因无法继续占用CPU运行,便会转入此状态。23 第十三章 多线程与网络编程13.3线程的生命周期13.3.2各状各状态的的转换事实上,此前我们已经进行了一些线程的控制,如调用start()方法将线程从新生状态转为可执
15、行状态,调用yield()方法将线程转为阻塞状态,也可以通过在run()方法中调用return语句将线程从运行状态转为死亡状态。在这些线程的状态间切换,从可运行状态转为运行状态只能由调度程序控制(通过设置线程优先级可以稍加干预,在14.3.3小节中将进行详细介绍),从新生状态转为可执行状态和从运行状态转为死亡状态很简单,而从运行状态到阻塞状态或可运行状态,以及从阻塞状态到可运行状态的切换,才是我们真正感兴趣的,也是线程状态转换的重点。当以下任一事件发生时,正在运行的线程将由运行状态转为阻塞状态:1.sleep()方法被调用,如 Thread.sleep(1000)。2.线程调用wait()方法
16、,并且等待一个指定的条件被满足。3.线程在I/O处阻塞。那么,如何让处于阻塞状态的线程进人可运行状态呢?下面给出可运行状态条件:1.线程处于睡眠(sleep)状态,那么必须在指定时间内睡眠。2.线程等待一个特定条件,那么必须由其他对象通过notify()或者notifyAll()方法来通知等待线程条件已改变。3.线程由于I/O阻塞,那么I/O操作必须完成。24 第十三章 多线程与网络编程13.3线程的生命周期13.3.2各状各状态的的转换若对线程各状态进行更好的转换控制,可能会用到以下Thread对象的方法,见表13-1。25 第十三章 多线程与网络编程13.3线程的生命周期13.3.2各状各
17、状态的的转换若对线程各状态进行更好的转换控制,可能会用到以下Thread对象的方法,见表13-1。26 第十三章 多线程与网络编程13.3线程的生命周期13.3.3线程的程的优先先级与与线程程调度度在Java语言中,对一个新建的线程,系统会分配一个默认的线程优先级:继承创建这个线 程的主线程的优先级(一般为普通优先级)。类Thread拥有三个代表线程优先级的整型静态 属性:1.NORM_PRIORITY:分配给线程的默认优先级,优先级别为5。2.MIN_PRIORITY:表示线程具有的最低优先级,优先级别为1。3.MAX_PRIORITY:表示线程具有的最高优先级,优先级别为10。它们都是公有
18、(public)属性,可以直接访问。通过getPriority()方法可以获取线程对象的当前优先级,通过setPriority()方法可以修改线程对象的优先级。在实际应用中,一般不需要修改线程的优先级,在此不给出实例,但以下关于线程优先级的特性是应该了解的:1.线程类的默认优先级为5,线程对象的默认优先级也是5。但是,如果在启动线程或创建线程前将其所属线程类的最高优先级(MAX_PRIORITY)修改到5以下,那就相当于创建出优先级比规定的最高优先级更高的线程。2.可以降低但无法提升线程类的最高优先级。3.修改线程类的优先级,不会对已经创建的该类的线程的优先级产生影响,但此后若修改(不管是降低
19、还是提升)这些线程的优先级,它们会自动变为修改后的线程类的优先级。27 第十三章 多线程与网络编程13.4线程同步在单线程的进程中,一个进程一次只能执行一个任务,不需要考虑两个或更多个任务同时 使用一个资源的问题,如两个任务同时修改同一个数据,或需在一台打印机上同时进行打印操作。然而在多线程环境下,多个线程试图同时使用相同且有限的资源的情况,是很有可能发生的,若不提供某种机制避免这种情况的出现,后果将不可预料且非常严重,如造成某些线程数据的不一致,使某些线程陷入无限循环,甚至破坏某些关键文件或数据库中的重要数据。事实上,在多任务操作系统中,多个进程同时使用相同且有限的资源的情况,也是时有发 生
20、的,操作系统为此提供了解决机制,用户不用担心。然而在进程内部的多线程环境下,如何避免这种资源冲突,是编程者必须考虑的问题。28 第十三章 多线程与网络编程13.4线程同步13.4.1线程同步程同步问题我们先来看看一个典型的生产者消费者问题,生产者生产数据后,消费者才能获取数据。其模型如图所示。生产者消费者模型 29 第十三章 多线程与网络编程13.4线程同步13.4.1线程同步程同步问题 30 第十三章 多线程与网络编程13.4线程同步13.4.1线程同步程同步问题 31 第十三章 多线程与网络编程13.4线程同步13.4.1线程同步程同步问题 32 第十三章 多线程与网络编程13.4线程同步
21、13.4.1线程同步程同步问题 33 第十三章 多线程与网络编程13.4线程同步13.4.2线程程间的的协作作通过在方法声明中加入synchronized关键字来声明synchronized()方法。如:public synchronized void put(int value)/*/synchronized()方法控制对类成员变量的访问:每个类实例对应一把锁,每个synchronized()方法都必须获得调用该方法的类实例的锁方能执行,否则线程处于阻塞状态。方法一旦被执行,就独占该锁,直到该方法返回才将锁释放,此后被阻塞的线程才能获得该锁,重新进人可执行状态。这种机制确保了同一时刻对于每一
22、个类实例,其所有声明为 synchronized的成员方法中至多只有一个处于可执行状态,从而有效避免了类成员变量的访问冲突。在Java中,不仅是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员方法声 明为synchronized,以控制对类的静态成员变量的访问。synchronized()方法的缺陷:若将一个大的方法声明为synchronized()将会大大影响效率,特别是若将线程类的方法run()声明synchronized(),由于在线程的整个生命期内一直处于运行状态,将导致它对本类任何synchronized()方法的调用都不会成功。当然,我们可以通过将访问类成员变量的代码放到专
23、门的方法中,将其声明为synchronized(),并在主方法中调用来解决这一问题,但Java为我们提供了更好的解决办法,那就是synchronized块。1.synchronized()方法 34 第十三章 多线程与网络编程13.4线程同步13.4.2线程程间的的协作作通过synchronized关键字来声明synchronized块。其语法如下:synchronized(syncObject)/访问关键数据的代码段 synchronized块用于指定一个同步代码段(即被花括号括起来的代码段)。同步代码段具有和synchronized()方法相同的同步特性,一个synchronized()方
24、法或同步代码段在执行时,其他synchronized()方法和同步代码段都不能执行。其中,小括号里的参数用于指定同步代 码段与对象syncObject(可以是类实例或类)的锁相关联。由于它适用于任意代码块,且可任意指定上锁的对象,故灵活性较高。2.synchronized 块 35 第十三章 多线程与网络编程13.4线程同步13.4.3线程同步程同步问题的解决的解决通过同步机制实现了线程间的协作,我们再来解决例13.6中数据不一致的问题。要使得生产者线程与消费者线程同步,经分析需要达到以下两个目标:1.这两个线程不能同时对box对象进行操作。Java线程可以通过锁定一个对象来达到 此目的。2.
25、这两个线程必须协调工作。例如:生产者线程必须通知消费者线程当前数字已产生,消 费者取走数字之后,通知生产者可以重新写人数字。线程类提供wait()、notify()、notifyAll()方 法来完成这些工作。对例13.6的类Box、生产者、消费者类进行修改。2.synchronized 块 36 第十三章 多线程与网络编程13.5多线程的应用多线程在界面设计(Applet或GUI设计)和网络中都有较多的应用,一些系统开销很大 的并发进程程序也可以修改为多线程程序,以节省系统资源。下面给出一个在小程序中使用 多线程的例子,它可以动态显示文字。例13.8是一个Java小程序。在屏幕上显示一串字符
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 核心 标称 技术 图文 课件 13
限制150内