第 13章 多线程
13.1 线程
13.2 创建线程
13.3 线程的状态
13.4 共享资源
13.5 习题
13.1 线程
程序的一次执行过程称为一个进程。进程是一个,自包含,的运行程序,有自己专用的内存地址。
线程是指一个程序中可以独立运行的片断,是进程中的一个单一而连续的控制流程。
一个进程可以包含多个线程,每个线程独立运行以执行特定的任务,而且同一进程内的多个线程间共享相同的内存。
13.2 创建线程
13.2.1 定义 Thread类的子类
13.2.2 实现 Runnable接口
13.2.1 定义 Thread类的子类
Thread:
– run()
//在子类中必须覆盖以说明线程自身的具体操作
– start()
//启动当前线程。它会为线程进行特殊的初始化,然后自动
//调用当前线程的 run()方法例 13-1 定义 Thread类的子类源代码 运 行
13.2.2 实现 Runnable接口
实现 Runnable接口,即定义其中惟一方法
run()的具体操作。此后,程序在需要创建线程时,只需以这个实现了 Runnable接口的类的对象为参数创建 Thread类的对象。
例 13-2 实现 Runnable接口源代码 运 行
13.3 线程的状态新建 可运行阻塞结束创建 start()
yield()
CPU时间片到
sleep()
wait()
suspend()
I/O block
...
notify()
notifyAll()
resume()
I/O unlock
...
run()结束
stop()
13.3 线程的状态(续)
新建状态
可运行状态
阻塞
结束例 13-3 线程的状态源代码 运 行
13.4 共享资源
13.4.1 线程同步
13.4.2 等待与通知
13.4.3 死锁
13.4.1 线程同步
多线程环境下,资源可以共享,因此可能存在两个或多个线程同时使用某一资源,从而造成资源冲突的情况。
例 13-4 演示资源冲突源代码 运 行
13.4.1 线程同步(续)
同步机制通过给对象加锁来防止多个线程同时访问某对象。要实现线程同步,通常需要将某些方法声明为同步的( synchronized)。
当程序调用任意同步方法时,如果该方法不是类方法,调用该方法的对象便会被锁定,
该对象的所有同步方法都无法再被调用,直至第 1个同步方法执行完毕并解除锁定;如果该方法是类方法,该方法所属类的所有对象都会被锁定,从而可以避免类变量被通过该类的不同对象同时访问。
13.4.1 线程同步(续)
为了避免例 13-4中的错误,可以将其中的方法 operateMoney()改写成如下形式:
public static synchronized void
operateMoney(int s)
{
a.setBalance(a.getBalance()+s);
}
源代码 运 行
13.4.2 等待与通知
public final void wait() throws
InterruptedException
//等待直至其他线程对同一对象调用 notifyAll()或 notify()
public final void wait(long timeout)
throws InterruptedException
//等待直至其他线程对同一对象调用 notifyAll(),notify()或参
//数指定的时间
public final void notifyAll()
//唤醒正在等待当前对象的所有线程
public final void notify()
//唤醒任意一个正在等待当前对象的线程
13.4.2 等待与通知(续)
等待与通知方法定义在 Object类中。
等待与通知方法必须出现在同步方法中,且调用等待方法时,锁定会被解除。
例 13-5 等待与通知源代码 运 行
13.4.3 死锁
一个线程试图调用另一对象的同步方法,但那个对象正被另一线程访问,因而处于锁定状态。此时只有那个对象的锁定状态解除,
该线程才会转入可运行状态。因此,线程可能会等待另一个线程;而另一个线程又可能正在等待下一个线程,依此类推;如果这个等待链封闭,即最后一个线程等待的正是第一个线程,便产生了死锁。
在死锁情况下,所有线程将陷入无休止的等待状态,无法继续运行。
13.5 习 题