Java线程编程全解析
立即解锁
发布时间: 2025-08-18 00:27:50 阅读量: 2 订阅数: 18 

### Java 线程编程全解析
#### 1. 线程编程基础示例
首先看一个简单的线程编程示例代码:
```java
public static void main(String[] args)
{
Thread clock = new CountDownClock();
ArrayList<Runnable> events
= new ArrayList<Runnable>();
events.add(new LaunchEvent(16, "Flood the pad!"));
events.add(new LaunchEvent(6, "Start engines!"));
events.add(new LaunchEvent(0, "Liftoff!"));
clock.start();
for (Runnable e : events)
new Thread(e).start();
}
```
这个示例的优点是不需要为每个 `LaunchEvent` 创建单独的变量,但要记得添加 `import java.util.*` 来使用 `ArrayList` 类。
#### 2. 线程协作问题及解决方案
上述倒计时应用存在一个重大缺陷:`CountDownClock` 和 `LaunchEvent` 线程严格依赖时间来协调活动。线程启动后相互独立运行,时间的随机变化会导致线程行为改变。例如,多次运行程序时,“Start engines!” 消息有时在 “T minus 6” 消息之后出现,有时在之前出现,这在实际应用中可能会造成严重后果。
为了解决这个问题,我们需要让线程之间能够通信。改进后的代码如下:
```java
import java.util.ArrayList;
// version 2.0 of the Countdown application
public class CountDownApp
{
public static void main(String[] args)
{
CountDownClock clock = new CountDownClock(20);
ArrayList<Runnable> events =
new ArrayList<Runnable>();
events.add(new LaunchEvent(16,
"Flood the pad!", clock));
events.add(new LaunchEvent(6,
"Start engines!", clock));
events.add(new LaunchEvent(0,
"Liftoff!", clock));
clock.start();
for (Runnable e : events)
new Thread(e).start();
}
}
interface TimeMonitor
{
int getTime();
}
class CountDownClock extends Thread
implements TimeMonitor
{
private int t;
public CountDownClock(int start)
{
this.t = start;
}
public void run()
{
for (; t >= 0; t--)
{
System.out.println("T minus " + t);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{}
}
}
public int getTime()
{
return t;
}
}
class LaunchEvent implements Runnable
{
private int start;
private String message;
TimeMonitor tm;
public LaunchEvent(int start, String message,
TimeMonitor monitor)
{
this.start = start;
this.message = message;
this.tm = monitor;
}
public void run()
{
boolean eventDone = false;
while (!eventDone)
{
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{}
if (tm.getTime() <= start)
{
System.out.println(this.message);
eventDone = true;
}
}
}
}
```
这个改进版本的主要亮点如下:
- 第 8 行:`CountDownClock` 类的构造函数现在接受一个参数来指定倒计时的起始时间,这里指定为 20 秒。
- 第 10 行:使用 `ArrayList` 来存储每个发射事件。
- 第 12 行:创建 `LaunchEvent` 对象时,将 `CountDownClock` 对象作为参数传递给其构造函数,以便在必要时调用时钟的 `abort` 方法。
- 第 19 行:启动时钟线程。
- 第 21 行:使用增强的 `for` 循环启动线程来运行 `LaunchEvent` 对象。
- 第 26 行:`TimeMonitor` 接口定义了一个 `getTime` 方法,用于获取时钟的当前状态。
- 第 31 行:`CountDownClock` 类实现了 `TimeMonitor` 接口。
- 第 33 行:使用私有字段 `t` 来存储倒计时的当前值。
- 第 35 行:`CountDownClock` 类的构造函数接受倒计时的起始时间作为参数。
- 第 42 行:`run` 方法中的 `for` 循环测试并递减 `t` 变量。
- 第 54 行:`getTime` 方法简单地返回 `t` 变量的值。
- 第 60 行:`LaunchEvent` 类的开始。
- 第 64 行:使用 `TimeMonitor` 类型的私有字段来访问倒计时时钟。
- 第 81 行:`while` 循环中调用 `Thread.sleep` 方法,每 10 毫秒检查一次倒计时时钟。
- 第 85 行:调用倒计时时钟的 `getTime` 方法,判断是否到了启动事件的时间。
下面是这个改进版本的流程图:
```mermaid
graph TD;
A[开始] --> B[创建 CountDownClock 对象];
B --> C[创建 ArrayList 存储事件];
C --> D[添加 LaunchEvent 对象到 ArrayList];
D --> E[启动时钟线程];
E --> F[启动 LaunchEvent 线程];
F --> G[时钟线程开始倒计时];
G --> H[LaunchEvent 线程每 10 毫秒检查时间];
H --> I{是否到时间};
I -- 是 --> J[显示消息并结束线程];
I -- 否 --> H;
G --> K{倒计时是否结束};
K -- 否 --> G;
K -- 是 --> L[结束程序];
```
#### 3. 使用 Executor
早期的 Java 线程机制比较原始,从 Java 1.5 开始,Java API 增加了许多用于精细控制线程运行的类。下面是使用 Java 1.5 线程类的新倒计时应用示例:
```java
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
class CountDownAppNew
{
public static void main(String[] args)
{
ScheduledThreadPoolExecutor pool =
new ScheduledThreadPoolExecutor(25);
Runnable flood, ignition, liftoff;
flood = new LaunchEventNew("Flood the pad!");
ignition = new LaunchEventNew("Start engines!");
liftoff = new LaunchEventNew("Liftoff!");
for (int t = 20; t >= 0; t--)
pool.schedule(new CountDownClockNew(t),
(long) (20 - t), TimeUnit.SECONDS);
pool.schedule(flood, 3L, TimeUnit.SECONDS);
pool.schedule(ignition, 13L, TimeUnit.SECONDS);
pool.schedule(liftoff, 19L, TimeUnit.SECONDS);
pool.shutdown();
}
}
class CountDownClockNew implements Runnable
{
int t;
public CountDownClockNew(int t)
{
this.t = t;
}
public void run()
{
System.out.println("
```
0
0
复制全文
相关推荐










