从零开始学Java 第13章 多线程

第13章  多线程
前面编写的程序都是单线程的。程序都是从main方法开始按照程序编写顺序的执行一条线索。但是在现实情况中有时候需要有多个线索同时运行。这就需要用到多线程的知识,Java对于多线程提供了良好的支持。本章的主要内容是介绍线程的基础、如何创建Java线程这些基本知识。并介绍了Java中多线程的应用以及线程同步等线程知识。
13.1  线程基本知识
本节主要内容是从总体上来介绍一下Java的线程。主要包括一些线程基本知识,包括什么是线程、线程与进程的区别,以及Java中的线程模型,即线程所处的各个状态。通过本节的学习读者可以对进程有一个初步的认识。
13.1.1  线程与进程
简单的说,进程就是执行中的程序。注意这样说不是说进程就是程序,程序本身不是程序,程序只是被动实体,如存储在硬盘上的文件。进程是一个活动的实体,它还需要一个程序计数器用来表示需要执行的下一条指令以及相关的资源。打开Windows的任务管理器选择进程选项卡,看到的就是当前运行中的各个进程。
13.1.2  Java的线程模型
每一个线程都有自身的声明周期,创建一个线程后就可以控制线程的启动、挂起和终止。一个线程在完整的声明周期中有五种状态:新建、就绪、运行、阻塞和终止。
1.新建状态
2.就绪状态
3.运行状态
4.阻塞状态
5.终止线程

13.2  创建Java线程
前一节介绍了线程的基本概念性知识,在这一节主要介绍如何创建Java线程。在Java中创建线程是非常简单的,主要有两者方式,继承Thread类或实现Runnable接口。通过本节的学习读者可以学会如何使用多线程来处理问题。
13.2.1  继承Thread类创建线程
一个类继承了java.lang.Thread类或其子类对象的时候,这个类就可以创建线程对象。这是实现多线程的最简单方法。使用该方法最重要的就是重写run方法,在run方法中执行相关的代码。
13.2.2  实现Runnable接口
另一种实现多线程的方法是实现Runnable接口.该接口只有一个run方法,在实现类中需要实现该接口的run方法。
在创建了一个类实现Runnable接口后,就可以通过它实现一个Thread类的对象。可以看到Thread类有多个构造函数,可以使用下面的几个通过实现Runnable接口类的对象来实例化Thread对象:
public Thread(Runnable target)
public Thread(Runnable target,String name)
在这两个构造函数中,参数target都指实现Runnable接口类的对象。它来构造线程对象,通过线程对象就能进行线程的操作。
13.2.3  两种方法的比较
下面简单的对这两种方式进行比较:
继承Thread类的方式最简单(前面看到了。如果是实现Runnable接口的话还是要用该类的对象来构造Thread对象),但是继承了该类就不能继承其它的类,这会影响程序开发。在大多数情况下,程序员希望自己的类有线程的能力。但是同时又希望不影响它的其它特性,包括继承,显然这样做是不能满足开发需求的。
实现Runnable接口不影响继承其它类,也不影响实现其它的接口。只是让该类多了线程的能力,显然这样做使得程序更加灵活。
在本章的程序中,主要使用后一种方式。
13.3  多线程的应用
前一节主要讲解了Java中实现线程的两种方式,这一节将会介绍多线程的应用。主要内容有多个线程的并发执行、线程的调度、线程的优先级以及Thread类中一些方法的使用。通过本节的学习读者对Java的线程机制有进一步的介绍。
13.3.1  多个线程并发执行
当有多个线程并发执行时,多次运行的结果可能不是唯一的。这是因为调度程序不能总按一个顺序调用线程。
Java对于线程启动后唯一能保证的是每个线程都被启动并且结束。但对于哪个线程先执行,哪个后执行,何时执行都没有保证。
13.3.2  线程优先级
线程之间是有优先级的,线程调度程序会优先调用优先级高的程序。Java在进行进程调度的策略是优先级高的线程有更大的可能性获得CPU,但不是优先级低的线程总不执行。优先级低的程序有时也可能比优先级高的线程更早执行。
在Java中Java的优先级用1到10之间的整数表示。数值越大则优先级越高,默认的线程优先级为5。改变线程优先级的方法setPriority():
public final void setPriority(int newPriority)
该方法是最终方法,在子类中不能重写该方法。用户可以通过getPriority来获得线程的优先级:
public final int getPriority()
13.3  线程调度
前面已经介绍了Java本身线程的调度是没有逻辑约束的,执行顺序以及执行时间是没有保证的。显然这样是不符合程序开发的要求的。Thread提供了一些方法来实现线程的调度,程序员可以通过它们自己来规定线程的执行。实际上在第一个程序中已经使用了进程调度。当时使用的方法是sleep方法。实现的功能就是交替的运行两个线程。这一节将会介绍几个方法来进行线程的调度。
13.3.1  休眠方法sleep()
在前面仅仅是使用了sleep()方法,并没有详细的进行介绍。sleep方法是让线程休眠一段指定的时间,等执行时间到了以后,线程会进入准备状态,等待线程调度程序的调度。
public static void sleep(long millis) throws InterruptedException
public static void sleep(long millis,int nanos) throws InterruptedException
这两个方法都能让线程进入休眠状态。不同的是后一个方法更精确,它在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠。

13.3.2  暂停方法yield()
yield方法的作用是暂停当前线程,运行其它的线程。该方法签名如下:
public static void yield()
调用该方法可以使当前整在执行的线程让出CPU使用权,进入准备状态。这样其它进程就能获得CPU的使用权。
13.3.3  挂起方法join()
join方法在一个线程需要等待另一个线程执行结束后再执行的情况下使用。它的方法签名如下:
public final void join() throws InterruptedException:等待调用该方法的线程终止
public final void join(long millis) throws InterruptedException:等待该线程终止的时间最长为millis毫秒。
public final void join(long millis,int nanos) throws InterruptedException:等待该线程终止的时间最长为millis毫秒+ nanos纳秒。

13.4  线程同步
多线程在提供了并发性以提高系统性能同时也带来了一些问题。如果两个或多个线程同时访问修改一个资源,则资源的同一性显然会出现问题。需要一种机制来确保某些资源在某一时刻只能被一个线程使用,这种机制就是同步。Java对同步操作提供了支持。本节主要介绍同步问题的由来以既Java如何解决同步问题。
13.4.1  同步问题的由来
为了便于理解同步问题,这里用一个实例来说明同步问题的由来。假如在一个办公室里只有一个打印机,假设这个打印机在收到信息后就把信息打印出来。有多个老师要使用它打印学生成绩,它们可能同时进行请求,即在打印机处理一个打印任务的时候又同时收到了其它的打印请求。老师窍M蛴』梢砸桓龈龅拇泶蛴∪挝瘢谡庵智榭鱿孪匀换岢鱿只炻摇

13.4.2  Java同步机制
在Java中实现同步有两种方式,同步方法和同步块。同步方法的使用很简单只需在需要同步的方法声明的时候加上synchronized关键字即可。
Java的同步是通过锁的机制来实现的,当进程进入同步方法的时候该线程将会获得同步方法所属对象的锁,一旦获得对象锁,则其它线程不能再执行被锁对象的其它任何同步方法。只有在同步方法执行完毕后释放锁之后才能执行。
13.5  死锁问题
线程死锁是指相互等待对方持有的资源时产生的一种特殊情况。一个线程需要申请一个资源才能继续执行,但是当前资源被另一个线程所占有。同时这个线程在等待当前线程占有的某个资源,这样二者就相互等待对方释放资源都处于等待状态。显然这中状态会无限的进行下去。

13.6  小结
本章主要对Java对多线程的机制进行了介绍。主要介绍了进程的模型,如何在Java创建多个线程,如何使用这些线程,以及线程调度以及线程优先级的知识。然后对线程同步问题进行了介绍,最后对线程的死锁问题进行了简单的介绍。如果可以有效的使用Java的多线程特性,就能编写出高效的程序,因为它可以把能够并发的子系统并发执行,从而提高运行效率。但是这种情况并不是绝对的,对线程的调度是需要进行上下文切换的,如果创建太多的程序会花费太多的系统开销在上下文切换上,从而降低系统的效率。

转载于:https://www.cnblogs.com/yoogoo/archive/2012/04/23/2467273.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值