《零点起飞学Java之线程.pptx》由会员分享,可在线阅读,更多相关《零点起飞学Java之线程.pptx(25页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第8章 线 程多线程编程是提高应用程序性能的重要手段之一。Java平台从开始就被设计成为多线程环境,从语言级上支持多线程。在Java语言中,提供了创建、启动、调度、同步等各种线程管理方法,下面会进行详细介绍。8.1 什么是线程多线程编程的目的是最大限度地利用CPU资源。当某一线程的处理不需要占用CPU,而只和I/O、内存等资源打交道时,让需要占用CPU资源的其他线程有机会获得CPU资源。要掌握多线程编程,需要弄清如下两个区别。1进程与线程的区别最初在Unix等多用户、多任务操作系统环境下,为了提高操作系统的并行性和资源利用率,提出了进程的概念。进程首先是个动态的过程,是程序的一次执行。进程用于
2、表示应用程序在内存环境中执行的基本单元,通常有如下一些特点。进程是操作系统环境中的基本成分、是系统资源分配的基本单位。进程在执行过程中有内存单元的初始入口点,并且进程存活过程中始终拥有独立的内存地址空间。进程的生存期状态包括创建、就绪、运行、阻塞和死亡等类型。1进程与线程的区别从用户角度来看,进程是应用程序的一个执行过程。从操作系统核心角度来看,进程代表的是操作系统分配的内存、CPU时间片等资源的基本单位,是为正在运行的程序提供的运行环境。随着对计算能力需求的不断增长,计算机系统中的资源也显得越发宝贵。频繁的进程状态切换会消耗大量的系统资源,为解决此问题,提出了线程的概念。线程仍然是处理器调度
3、的基本单位,但不再是资源分配的单位。线程的状态切换比进程切换的负担要小得多。Java语言从开始就被设计成为多线程环境,从语言级别上支持多线程。2线程对象和线程的区别另一个重要的区别是线程对象和线程的区别。线程对象是指可以产生线程的对象,如在Java语言中的Thread对象、Runnable对象。线程是指正在执行的一个指令序列。在Java语言中是指从一个线程对象的start()方法执行开始,运行run()方法体中的那一段相对独立的过程。对线程概念有了基本认识之后,下面章节就详细介绍Java语言中的多线程编程方法。8.2 使用线程要想执行一个线程,首先需要对其进行创建和启动。线程的创建完成线程的定
4、义,实现线程执行时所需完成的功能;线程的启动是对实例化的线程进行启动,使其获得执行的机会。对这两部分内容,下面分别进行介绍。8.2.1 创建线程要使用线程,首先需要创建线程。在Java语言中,创建线程有两种方式,可以继承java.lang.Thread类或者实现Runnable接口。下面对这两种创建方式分别进行介绍。1继承Thread类Java语言中定义了线程类Thread。用户可以通过继承Thread类,覆盖其run()方法创建自己的线程类。通常继承Thread类创建线程的语法格式如图8.1所示。2实现Runnable接口另一种创建线程类的方式是实现Runnable接口。如果自定义的线程类还
5、要继承其他类,这时就不能采用第一种方式来创建。由于Java语言不支持类的多继承,却可以实现多个接口,所以这种情况可以采用实现Runnable接口的方式创建。通常实现Runnable接口创建线程的语法格式如图8.2所示。8.2.2 启动线程线程创建完成后,通过线程的启动来执行线程。类Thread定义了start()方法用来完成线程的启动。针对两种不同的线程创建方式,下面分别介绍其启动方法。1继承Thread类方式线程的启动继承Thread类方式的线程启动非常简单,只要创建线程类实例后调用其start()方法即可。启动线程的语法格式如图8.3所示。start()方法是类Thread定义的方法,通常
6、不建议对其覆盖。2实现Runnable接口线程的启动实现Runnable接口创建的线程首先转换为Thread类,然后调用Thread类的start()方法启动线程。通常将实现了Runnable接口创建的线程类实例作为构造方法参数,使用Thread的构造方法转换为Thread类。启动线程的语法格式如图8.4所示。8.3 线程的生命周期线程从其创建到死亡具有一个完整的生命周期,在整个生命周期中处于各种状态。线程的状态表明线程当前可以进行的活动。一个生命周期内的线程主要包括创建、就绪、运行、阻塞、死亡状态,如图8.5所示。1创建在线程类使用new关键字实例化之后且在调用start()方法之前,线程处
7、于创建状态。处于创建状态的线程仅仅分配了内存空间,属于生命周期的初始状态。2就绪在线程调用了start()方法后即处于就绪状态。处于就绪状态的线程具备了除CPU之外运行所需的所有资源。就绪状态线程排队等待CPU,由系统调度为其分配。3运行处于就绪状态的线程获得CPU之后即处于运行状态。处于运行状态的线程才开始真正执行线程run()方法的内容。4阻塞处于运行状态的线程如果因为某种原因不能继续执行,则进入阻塞状态。阻塞状态与就绪状态的不同是:就绪状态只是因为缺少CPU而不能执行,而阻塞状态是由于各种原因引起线程不能执行,不仅仅是缺少CPU。引起阻塞的原因解除以后,线程再次转为就绪状态,等待分配CP
8、U运行。5死亡当线程执行完run()方法的内容或被强制终止时,线程处于死亡状态,线程的整个生命周期结束。线程在整个生命周期中始终处于某种状态,从一种状态到另一种状态的转换由线程调度方法实现。8.4 线程的调度处于生命周期中的线程,通过调度实现各种状态间的转换。线程的调度是使用各种线程调度方法,如setPriority()、sleep()、yield()、join()等,对线程进行不同的操作。对于各种线程调度方法,下面分别进行介绍。8.4.1 线程优先级线程优先级是指线程在被系统调度执行时的优先执行级别。在多线程程序中,往往是多个线程同时等待被调度执行。然而,每个线程的重要程度通常不一样,在同等
9、条件下,有些重要线程需要优先执行。在Java语言中,通过调用setPriority()方法为线程设置优先级。优先级用110的数字表示,数字越大,优先级越高。8.4.2 线程休眠sleep()对于正在执行的线程,可以调用sleep()方法使其放弃CPU进行休眠,此线程转为阻塞状态。sleep()方法包含long型的参数,用于指定线程休眠的时间,单位为毫秒。sleep()方法还会抛出可控异常InterruptedException,程序需要对此异常进行处理。下面通过示例讲述sleep()方法的使用。8.4.3 线程让步yield()对于正在执行的线程,可以调用yield()方法使其重新排队,将CP
10、U让给排在后面的线程,此线程转为就绪状态。另外,yield()方法只让步给高优先级或同等优先级的线程,如果后面是低优先级线程,则继续执行此线程。yield()方法没有参数,也没有声明抛出任何异常。下面通过示例讲述yield()方法的使用。注意:由于不能确定线程间何时作出让步,故程序每次输出结果都不相同。8.4.4 线程等待join()对于正在执行的线程,可以调用join()方法等待其结束,然后再执行其他程序。join()方法有几种重载形式。其中,不带任何参数的join()方法,等待线程执行结束为止,其他重载形式可参考JDK API。Join()方法也会抛出可控异常InterruptedExce
11、ption,程序需要对此异常进行处理。下面通过示例讲述join()方法的使用。8.5 线程之间同步当多个线程操作同一个共享资源时,比如读写同一个变量,存在着资源竞争的问题。为了解决此类问题,需要使用同步机制。在Java语言中,利用synchronized关键字实现线程同步。同步方法的语法格式如图8.6所示。8.6 小 结本章介绍了Java语言中的多线程编程,包括创建与启动线程、线程的生命周期、线程调度、线程同步等知识。本章最后给出了一个完整的实例。其中各种线程调度方法是本章的难点。多线程编程属于程序语言编程中的高级知识,多学习一些操作系统相关方面的理论知识能够更好地掌握多线程编程。第9章将介绍Java语言中输入输出流方面的知识。