多线程入门
从现在开始,我们进入并发编程的学习,那么首先我们要了解的就是多线程。
Java单线程程序已经能够完成逻辑处理,为什么还需要“多线程”呢?
单线程只能同时做一件事,无法同时进行多个任务。如果某个操作耗时较长,会引起主线程的阻塞,导致程序变慢。
单线程像是你在同一时间只能写作业,而有些人却能够边听歌,看综艺,还能写作业。
进程与线程?
在操作系统中,我们常听到“进程”和“线程”这两个词,它们到底是什么?两者有什么区别?为什么需要多线程而不是直接使用多个进程?
| 概念 | 定义 |
|---|---|
| 进程 | 操作系统资源分配的基本单位。每个运行中的程序就是一个进程,拥有独立的内存空间和系统资源。 |
| 线程 | 进程中执行的最小单元,是CPU调度的基本单位。一个进程中可以包含多个线程,它们共享进程的资源。 |
简单来说,每个程序就是一个进程,一个进程可以拥有多个线程
Java 中创建多线程的常见方式
继承Thread类
1 | class MyThread extends Thread { |
实现Runnable接口
1 | class MyRunnable implements Runnable { |
实现 Runnable 更加灵活、解耦性好,是更推荐的做法。
从上述内容看到,不论是继承Thread类还是实现Runnable接口,要想实现多线程的处理逻辑就要重写run()方法。
因为默认的run()是不干活的,该方法来源于接口Runnable
1 |
|
Thread类也实现了这个接口,这也是其run()的来源
1 | public class Thread implements Runnable {...} |
看到这里,你可能有点糊涂,感觉没什么问题,但有什么地方是不通的。可能会有这样的疑问:Runnable是什么? Thread又是什么?
还记得Java最最最重要的特点吗? 万物皆对象,一切都围绕 “ 对象行为(方法)+ 状态(属性)” 来组织。在这种思想下,“逻辑”本身也可以抽象成一个对象。Runnable 就是一个对“任务逻辑”的对象化表达。
Runnable 接口是什么?
1 |
|
这是个函数式接口,里面只有一个抽象方法run(),表示要执行的任务逻辑 ;
换句话说,Runnable是对“任务”的对象化封装,将任务执行的逻辑封装成对象交给线程去执行。
来看一段代码:
1 | Runnable task = () -> System.out.println("Running in thread!"); |
task是一个对象(它实现了Runnable接口);- 它代表一段“行为”;
- 我们把它传给
Thread类构造方法,Thread就知道该线程该执行什么内容。
start() 和 run()
Thread.start() 是启动线程的入口,不能直接调用 run(),那只是普通方法调用!
只有调用start()方法,在栈中才会创建一个线程!