当前位置:文档之家› 第七章 多线程与异常处理

第七章 多线程与异常处理


7.2 线程的创建
在Java语言中,线程也是一种对象, 但并非任何对象都可以成为线程。 只有实现Runnable接口或继承了 Thread类的对象才能成为线程。
Thread类
Thread类中的主要的方法包括: start()方法 interrupt()方法 join()方法 run()方法。 其中start()方法与run()方法最为常用,start() 方法用于启动线程,run()方法为线程的主体方法, 可以根据需要重写run()方法。
7.2.3 实现Runnable接口
从本质上讲,Runnable是Java语言中用以实 现线程的接口,任何实现线程功能的类都必须实现 这个接口。 Thread类就是因为实现了Runnable接口,所 以继承它的类才具有了相应的线程功能。
实现Runnable接口
虽然可以使用继承Thread类的方式实现线程,但 是由于在Java语言中,只能继承一个类,如果用户定义 的类已经继承了其他类,就无法再继承Thread类,也就 无法使用线程,于是Java语言为用户提供了一个接口, ng.Runnable,实现Runnable这个接口与继承 Thread类具有相同的效果,通过实现这个接口就可以使 用线程。 Runnable接口中定义了一个run()方法,在实例化 一个Thread对象时,可以传入一个实现Runnable接口 的对象作为参数,Thread类会调用Runnable对象的run() 方法,继而执行run()方法中的内容。 △
7.3 线程的生命周期


线程主要有以下状态: 创建 可执行 非可执行 消亡
创建
当实例化一个Thread对象并执行start()方法后, 线程进入“可执行”状态,开始执行,虽然多线程 给用户一种同时执行的感觉,但事实上在同一时间 点上,只有一个线程在执行,只是线程之间转换的 动作很快,所以看起来好像同时在执行一样。
7.5.2 线程的挂起
线程的挂起操作实质上就是使线程进入 “非可执行”状态下,在这个状态下,CPU不 会分给线程时间段,进入这个状态可以用来暂 停一个线程的运行,在线程挂起后,可以通过 重新唤醒线程来使之恢复运行。这个过程在外 表看来好像什么也没有发生过,只是线程很慢 地执行一条指令。
线程的挂起
线程的优先级
绝大多数操作系统都支持Time slicing,简单 地说就是操作系统会为每个线程分配一小段CPU时 间,时间一到就换下一个线程,即便这个线程没有 执行完毕。对于不支持Time slicing的操作系统,每 个线程必须执行完毕后,才轮到下一个线程,如果 需要此线程礼让一下其他线程,可以使用Thread类 中的yield()方法。
(4)基于Runnable对象并指定线程名称的构造方法 该构造方法接收Runnable对象和线程名称的字符串。 语法格式为:
Thread thread=new Thread(Runnable simple, String name);
simple:实现Runnable接口的对象。 name:线程名称。
可执行
当线程启用start()方法后,进入“可执行”状态,执 行用户覆写的run()方法。 一个线程进入“可执行”状态下,并不代表它可以一 直执行到run()结束为止,事实上它只是加入此应用程序执 行安排的队列中,也就是说,这个线程加入了进程的线程执 行队列中,对于大多数计算机而言,只有一个处理器,无法 使多个线程同时执行,这时需要合理安排线程执行计划,让 那些处于“可执行”状态下的线程合理分享CPU资源。 所以,一个处在“可执行”状态下的线程,实际上可 能正在等待取得CPU时间,也就是等候执行权,在何时给 予线程执行权,则由Java虚拟机和线程的优先级来决定。
Thread类
Thread类有4个最常用构造方法。 (1)默认构造方法 默认的构造方法,没有参数列表。语法格式为:
Thread thread=new Thread();
(2)基于Runnable对象的构造方法 该构造方法包含了Runnable类型的参数,它是实现 Runnable接口的类的实例对象,基于该构造方法创建的线 程对象,将线程的业务逻辑交由参数所传递的Runnable对 象去实现。语法格式为:
public class A extends Thread{ Thread B; run(){ B.join(); …… } }
// 在线程A中执行线程B
线程的挂起 wait()与notify()方法
wait()方法同样可以对线程进行挂起操作,调用 wait()方法的线程将进入“非可执行”状态,使用wait() 方法有两种方式。 语法格式为:
当一个线程进入“非可执行”状态,也就是挂起 状态时,必然存在某种原因使其不能继续运行,这些原 因可能是如下几种情况。 (1)通过调用sleep()方法使线程进入休眠状态, 线程在指定时间内不会运行。 (2)通过调用join()方法使线程挂起,如果线程A 调用线程B的join()方法,那么线程A将被挂起,直到线 程B执行完毕为止。 (3)通过调用wait()方法使线程挂起,直到线程 得到了notify()和notifyAll()消息,线程才会进入“可执行” 状态。 (4)线程在等待某个输入/输出完成。
Runnable接口
实现Runnable接口的类就可以成为线程, Thread类就是因为实现了Runnable接口所以才具 有了线程的功能。 Runnable接口只有一个方法就是run()方法, 实现Runnable()接口后必须实现run()方法。
7.2.2 继承Thread类
在Java语言中要实现线程功能,可以继承 ng.Thread类,这个类已经具备了创建和运 行线程的所有必要架构,通过重写Thread类中run() 方法,以实现用户所需要的功能,实例化自定义的 Thread类,使用start()方法启动线程。 △
线程的挂起 sleep()方法
sleep()方法是使一个线程的执行暂时停止的方法, 暂停的时间由给定的毫秒数决定。 语法格式为:
Thread.sleep(long millis)
millis:必选参数,该参数以毫秒为单位设置线程 的休眠时间。 执行该方法后,当前线程将休眠指定的时间段, 如果任何一个线程中断了当前线程的休眠,该方法将抛 出InterruptedException异常对象,所以在使用sleep()方 法时,必须捕获该异常。
第7章 多线程与异常处理
第7章 多线程与异常处理
7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 线程概述 线程的创建 线程的生命周期 线程的优先级 线程的控制 线程的同步 线程通信 多线程产生死锁 异 常
7.1 线程概述





此前的Java程序只做一件事—单线程的。 同时做多(>2)件事的情况—多线程的。 Java支持多线程,多线程程序同时支持多个执 行片段,视情况同步或异步工作。 进程—OS的程序,正在运行程序。 线程—进程内部的任务,进程中的实体,单一 顺序控制流,一个进程可拥有多个线程。 线程必有父进程,OS为进Байду номын сангаас分配资源,进程 内线程共享该资源,线程间共享信息容易。
thread.wait(1000);
或者:
thread.wait(); thread.notify();
thread:线程对象。 第一种方式给定线程挂起时间
线程的挂起 wait()与notify()方法
第二种方式是wait()与notify()方法配合使用,这种 方式让wait()方法无限等下去,直到线程接收到notify() 或则notifyAll()消息为止。 wait()、notify()、notifyAll()不同于其他线程方法, 这3个方法是ng.Object类的一部分,而Object类 是所有类的父类,所以这3个方法会自动被所有类继承 下来,wait()、notify()、notifyAll()都被声明为final类, 所以无法重新定义。
线程的挂起 sleep()方法
例如:想让线程休眠1.5秒钟,即1 500毫 秒,可以使用如下代码。
try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } // 使线程休眠1500毫秒 // 捕获异常 // 输出异常信息
非可执行
在“可执行”状态下,线程可能被执行完毕, 也可能没有执行完毕,处于等待执行权的队列中, 当使线程离开“可执行”状态下的等待队列时,线 程进入“非可执行”状态。 可以使用Thread类中的wait()、sleep()方法使 线程进入“非可执行”状态。
消亡
当run()方法执行完毕后,线程自动消亡,当 Thread类调用start()方法时,Java虚拟机自动调用 它的run()方法,而当run()方法结束时,该Thread 会自动终止。以前Thread类中存在一个停止线程的 stop()方法,不过它现在被废弃了,因为调用这个 方法,很容易使程序进入不稳定状态。
Thread thread=new Thread(Runnable simple);
simple:实现Runnable接口的对象
Thread类
(3)指定线程名称的构造方法 该构造方法包含了String类型的参数,这个参数将作 为新创建的线程对象的名称。语法格式为:
Thread thread=new Thread("ThreadName");
7.4 线程的优先级
在Java语言中,线程有执行的优先级别,优先 级的范围是1~10,默认值为5,可以使用Thread 类中setPriority()方法来设定线程的优先级,但必须 是在1~10的范围内,否则会出现异常。 优先权较高的线程会被提前执行,当它执行完 毕才会轮到优先权较低的线程执行。如果优先权相 同,那么采用轮流执行的方式。
相关主题