Java 多线程创建方式实战解析:Thread类与Runnable接口的应用
一、原题完整代码呈现
以下是计算机二级Java考试中关于多线程创建的典型题型,主要考察Thread类继承、Runnable接口实现、线程启动及循环控制,包含5处需要填写的空白(标记为//*********Found********
):
import java.io.*;
import java.lang.Thread;
class MyThread extends Thread{
public int x = 0;
//*********Found********
public void _______________(){
System.out.println(++x);
}
}
//*********Found********
class RThread implements _______________{
private int x = 0;
public void run(){
System.out.println(++x);
}
}
public class Java_3 {
public static void main(String[] args) throws Exception{
for(int i=0;i<5;i++){
Thread t = new MyThread();
//*********Found********
t._______________();
}
Thread.sleep(1000);
System.out.println();
//*********Found********
RThread r = new _______________();
//*********Found********
for(int i=0;i<_______________;i++){
Thread t = new Thread(r);
t.start();
}
}
}
二、空白处逐一解析与解答
1. 第一处空白:重写Thread类的run()方法
答案:run
//*********Found********
public void run(){
System.out.println(++x);
}
解析: MyThread
类继承自Thread
类,Thread
类的核心方法是run()
,该方法定义了线程的执行逻辑。当线程启动(调用start()
)后,会自动执行run()
方法中的代码。因此需要重写run()
方法,填写run
。
2. 第二处空白:实现Runnable接口
答案:Runnable
//*********Found********
class RThread implements Runnable{
解析:
Java中创建线程的另一种方式是实现Runnable
接口(该接口仅包含run()
方法)。RThread
类通过implements Runnable
声明实现该接口,并在类中定义run()
方法作为线程执行逻辑,因此填写Runnable
。
3. 第三处空白:启动线程(Thread子类实例)
答案:start
//*********Found********
t.start();
解析: MyThread
是Thread
的子类,创建线程实例后,需调用start()
方法启动线程(而非直接调用run()
)。start()
方法会触发JVM创建新线程并执行run()
方法,直接调用run()
仅为普通方法调用,不会启动新线程,因此填写start
。
4. 第四处空白:实例化Runnable实现类
答案:RThread
//*********Found********
RThread r = new RThread();
解析:
此处需要创建RThread
类的实例(该类实现了Runnable
接口),用于作为线程的任务对象。实例化语法为new 类名()
,因此填写RThread
。
5. 第五处空白:控制Runnable线程的数量
答案:5
//*********Found********
for(int i=0;i<5;i++){
解析:
前一个循环创建了5个MyThread
线程,为保持对称性且符合常规测试场景,此处循环也应创建5个线程。通过i<5
控制循环次数,确保启动5个基于Runnable
的线程,因此填写5
。
三、完整正确代码
四、程序功能与运行说明
程序功能
该程序通过两种方式创建并启动多线程,对比不同线程创建方式的特性:
- 继承
Thread
类(MyThread
):创建5个独立线程,每个线程有自己的x
变量 - 实现
Runnable
接口(RThread
):创建5个线程共享同一个Runnable
实例,共用x
变量
运行说明
第一阶段(
MyThread
线程):- 循环创建5个
MyThread
实例,每个实例调用start()
启动线程 - 每个线程的
x
是独立的实例变量,因此每个线程执行++x
后输出1
- 输出结果(顺序可能因线程调度不同而变化):
1 1 1 1 1
(换行前)
- 循环创建5个
延迟与换行:
Thread.sleep(1000)
暂停1秒,确保第一阶段线程执行完毕System.out.println()
输出空行,分隔两个阶段的结果
第二阶段(
RThread
线程):- 创建1个
RThread
实例r
,循环创建5个Thread
实例,均传入r
- 5个线程共享
r
的x
变量(私有变量),因此++x
会累积递增 - 输出结果(可能因线程并发导致顺序不定,但最终包含1-5):
1 2 3 4 5
- 创建1个
五、核心知识点总结
线程创建的两种方式
方式一:继承
Thread
类- 步骤:
class 类名 extends Thread
→ 重写run()
方法 → 创建实例并调用start()
启动 - 特点:每个线程是独立的对象,实例变量不共享(如
MyThread
的x
)
- 步骤:
方式二:实现
Runnable
接口- 步骤:
class 类名 implements Runnable
→ 实现run()
方法 → 创建Thread
实例时传入该类对象,调用start()
启动 - 特点:多个线程可共享同一个
Runnable
实例的变量(如RThread
的x
),更适合资源共享场景
- 步骤:
线程启动与执行
启动方法:必须调用
start()
方法,而非直接调用run()
start()
:由JVM创建新线程,自动调用run()
,实现并发执行run()
:直接调用仅为普通方法,在当前线程中执行,无并发效果
- 执行逻辑:
run()
方法是线程的入口点,线程启动后会执行该方法中的代码
变量共享特性
- 继承
Thread
:每个线程是独立实例,实例变量(如MyThread.x
)各自独立,修改互不影响 - 实现
Runnable
:多个线程共享同一个Runnable
实例,其成员变量(如RThread.x
)会被所有线程共享,需注意线程安全(本题未处理,可能出现输出顺序混乱)
- 继承
线程调度与延迟
- 线程调度:Java线程调度由JVM决定,输出顺序可能不确定(体现多线程并发特性)
- 延迟控制:
Thread.sleep(1000)
使当前线程暂停1000毫秒(1秒),用于分隔两个阶段的执行,避免输出混杂
六、常见错误与应试技巧
常见错误分析
- 第一处空白方法名错误:写成
run()
以外的方法(如start()
),导致线程启动后无执行逻辑 - 第二处空白接口名错误:写成
Thread
(继承而非实现)或拼写错误(如Runnable
少字母),无法作为线程任务 - 第三处空白启动方法错误:写成
run()
(直接调用方法,无新线程创建)或start()
拼写错误,线程无法并发执行 - 第四处空白实例化错误:写成其他类名(如
MyThread
),与后续new Thread(r)
不兼容 - 第五处空白循环次数错误:写成非5的数字(如
4
或6
),破坏程序对称性,与预期输出不符
- 第一处空白方法名错误:写成
应试技巧
- 线程创建口诀:"继承Thread重run,实现Runnable也重run;启动都用start,千万别把run来调"
- 变量共享判断:"Thread子类各管各,Runnable共享同一货"
- 并发理解:"线程启动顺序定,执行顺序不一定,调度由JVM决定"
- 调试技巧:输出线程名称(
Thread.currentThread().getName()
),观察线程执行顺序
通过本题,我们掌握了Java中两种线程创建方式的实现、线程启动的正确方法、变量共享特性及多线程并发的基本表现。理解这两种方式的差异(尤其是资源共享方面),对选择合适的线程实现方式解决实际问题具有重要意义。