Java 多线程的创建
1. 前言
本节内容重点需要掌握 Java 多线程的三种创建方式,具体内容如下:
- Java 线程类 Thread 继承结构,这是 JDK Thread 源码的类结构,是了解 Thread 类的第一步;
- 掌握多线程的三种创建方式,这是本节的重点内容。本节所有内容都是围绕改话题进行的讲解;
- 了解多线程不同创建方式的优劣,不同的创建方式有自己的优势和劣势,本节还会推荐同学使用第二种接口实现的创建方式;
- 掌握 Thread 类常用方法,这也是本节的重点内容,其常用方法使我们开发过程中经常涉及到的,必须要熟记于心;
- Thread 类编程实验实战,学习完多线程的创建方式,我们需要进行实战代码巩固本节的内容。
2. Thread 类结构介绍
介绍: 位于 java.lang 包下的 Thread 类是非常重要的线程类。学习 Thread 类的使用是学习多线程并发编程的基础。它实现了 Runnable 接口,其包集成结构如下图所示。
3. 多线程的三种创建方式
Java 多线程有 3 种创建方式如下:
- 方式一:继承 Thread 类的方式创建线程;
- 方式二:实现 java.lang.Runnable 接口;
- 方式三:实现 Callable 接口。
在接下来的内容中,会详细的对这 3 种创建方式进行详细的讲解。
4. 多线程实现之继承 Thread 类
实现步骤:
- 步骤 1:继承 Thread 类 extends Thread;
- 步骤 2:复写 run () 方法,run () 方法是线程具体逻辑的实现方法。
实例:
/\*\*
\* 方式一:继承Thread类的方式创建线程
\*/
public class ThreadExtendTest extends Thread{ //步骤 1
@Override
public void run() { //步骤 2
//run方法内为具体的逻辑实现
System.out.println("create thread by thread extend");
}
public static void main(String[] args) {
new ThreadExtendTest(). start();
}
}
5. 多线程实现之实现 Runnable 接口
Tips:由于 Java 是面向接口编程,且可进行多接口实现,相比 Java 的单继承特性更加灵活,易于扩展,所以相比方式一,更推荐使用方式二进行线程的创建。
实现步骤:
- 步骤 1:实现 Runnable 接口,implements Runnable;
- 步骤 2:复写 run () 方法,run () 方法是线程具体逻辑的实现方法。
实例:
/\*\*
\* 方式二:实现java.lang.Runnable接口
\*/
public class ThreadRunnableTest implements Runnable{//步骤 1
@Override
public void run() {//步骤 2
//run方法内为具体的逻辑实现
System.out.println("create thread by runnable implements");
}
public static void main(String[] args) {
new Thread(new ThreadRunnableTest()). start();
}
}
6. 多线程实现之实现 Callable 接口
Tips:方式一与方式二的创建方式都是复写 run 方法,都是 void 形式的,没有返回值。但是对于方式三来说,实现 Callable 接口,能够有返回值类型。
实现步骤:
- 步骤 1:实现 Callable 接口,implements Callable;
- 步骤 2:复写 call () 方法,call () 方法是线程具体逻辑的实现方法。
实例:
/\*\*
\* 方式三:实现Callable接口
\*/
public class ThreadCallableTest implements Callable<String> {//步骤 1
@Override
public String call() throws Exception { //步骤 2
//call 方法的返回值类型是 String
//call 方法是线程具体逻辑的实现方法
return "create thread by implements Callable";
}
public static void main(String[] args) throws ExecutionException, InterruptedException{
FutureTask<String> future1 = new FutureTask<String>(new ThreadCallableTest());
Thread thread1 = new Thread(future1);
thread1. start();
System.out.println(future1.get());
}
}
7. 匿名内部类创建 Thread
首先确认,这并不是线程创建的第四种方式,先来看如何创建。
实例:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通过匿名内部类创建Thread");
}
});
我们从代码中可以看出,还是进行了一个 Runnable 接口的使用,所以这并不是新的 Thread 创建方式,只不过是通过方式二实现的一个内部类创建。
Tips: 在后续章节讲解 join 方法如何使用 的时候,我们会采用匿名内部类的方式进行多线程的创建。
8. Thread 类的常用方法介绍
方法 | 作用 |
---|---|
start() | 启动当前的线程,调用当前线程的 run ()。 |
run() | 通常需要重写 Thread 类中的此方法,将创建要执行的操作声明在此方法中。 |
currentThread() | 静态方法,返回代码执行的线程。 |
getName() | 获取当前线程的名字。 |
setName() | 设置当前线程的名字。 |
sleep(long millitime) | 让当前进程睡眠指定的毫秒数,在指定时间内,线程是阻塞状态。 |
isAlive() | 判断进程是否存活。 |
wait() | 线程等待。 |
notify() | 线程唤醒。 |
9. Thread 编程测验实验
实验目的:对 Thread 的创建方式进行练习,巩固本节重点内容,并在练习的过程中,使用常用的 start 方法和 sleep 方法以及 线程的 setName 方法。
实验步骤:
- 使用 Runnable 接口创建两条线程 :t1 和 t2;
- 请设置线程 t1 和 t2 的线程名称分别为 “ThreadOne” 和 “ThreadTwo”;
- 线程 t1 执行完 run () 方法后,线程睡眠 5 秒;
- 线程 t2 执行完 run () 方法后,线程睡眠 1 秒。
请先自行实现,并将结果与所提供的答案进行复核。
public class ThreadTest implements Runnable{
@Override
public void run() {
System.out.println("线程:"+Thread.currentThread()+" 正在执行...");
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ThreadTest());
t1.setName("ThreadOne");
Thread t2 = new Thread(new ThreadTest());
t2.setName("ThreadTwo");
t1. start();
t1.sleep(5000);
t2. start();
t1.sleep(1000);
System.out.println("线程执行结束。");
}
}
执行结果:
线程:Thread[ThreadOne,5,main] 正在执行...
线程:Thread[ThreadTwo,5,main] 正在执行...
线程执行结束。
Tips: 该测验主要针对线程的创建方式以及线程的执行 start 方法的测验,并附带进行了线程 setName 和线程 sleep 方法的使用。对于线程其他常用方法的使用如 wait 方法等,会在后续小节进行详细讲解。
10. 小结
本节课程的重中之重就是掌握线程的 3 中创建方式以及 Thread 类常用方法的使用,一定要掌握并吃透。
线程 Thread 的创建方式以及执行方式是学习多线程并发的前提条件,我们在使用无返回值的多线程创建方式时,推荐使用方式二进行多线程的创建。如果针对具体的业务场景需要使用多线程执行结果的返回值,那我们需要使用方式三进行线程的创建。