简介
是指从软件或者硬件上实现多个线程并发执行的技术
具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能
简单来说就比如你正在听歌,但是你想要在听歌的同时发布评论并且听歌不受影响,这就是多线程了,一共两个线程,一条线程供你听歌不干其他的事情就光顾着你听歌就行,而另一条线程则是供你发布评论,两条线程同时工作,但又互不影响
概念
并发和并行
进程和线程
- 进程:正在运行的软件
- 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位
- 动态性:进程的实质是程序的一次执行过程,进程是动态产生的,动态消亡的
- 并发性:任何进程都可以和其他的进程一起并发执行
- 线程:是进程中的单个顺序控制流,是一条执行的路径
- 单线程:一个进程如果只有一条执行的路径,则被称为单线程程序
- 多线程:一个进程如果有多个执行路径,则被成为多线程程序
多线程实现
一个有三种实现方式:
- 继承
Thread
类的方式进行实现 - 实现
Runnable
接口的方式进行实现 - 利用
Callable
和Future
接口的方式实现
继承Thread类
- 定义一个类继承
Thread
- 在类中重写
run()
方法 - 创建类的对象,启动线程
单线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Main { public static void main(String[] args) { Run r = new Run(); r.start(); } }
class Run extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(i); } } }
|
run
方法里面写的内容就是线程开启之后要执行的事情
因为只有一条线程也可以算是单线程
多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Main { public static void main(String[] args) { Run r1 = new Run(); Run r2 = new Run(); r1.start(); r2.start(); } }
class Run extends Thread { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(i); } } }
|
因为线程的执行是CPU来决定的,所以第一次运行和第二次运行的结果可能不一样,线程之间的执行有一个随机性
小问题
run和stage方法有什么区别
run方法这个用来重写是因为里面的内容是线程要执行的内容所以要重写
run和stage方法有什么区别
run:调用run方法是就跟调用普通方法一样,当执行完成第一个方法之后在进行执行第二条——并没有开启线程
stage:启动线程,然后由虚拟机调用run方法
实现Runnable接口
- 定义一个类实现
Runnable
接口 - 在类中重写
run
方法 - 创建类的对象
- 创建
Thread
类的对象,把之前创建的类对象作为构造方法的参数,启动线程
单线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Main { public static void main(String[] args) { Run r = new Run(); Thread thread = new Thread(r); thread.start(); } }
class Run implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(i); } } }
|
多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class Main { public static void main(String[] args) { Run r1 = new Run(); Thread thread1 = new Thread(r1); thread1.start();
Run r2 = new Run(); Thread thread2 = new Thread(r2); thread2.start(); } }
class Run implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(i); } } }
|
Callable和Future
- 定义一个类并实现
Callable
- 在类中重写
call()
方法 - 创建类对象
- 创建
Future
的实现类FutureTask
对象,把类对象作为构造方法的参数 - 创建
Thread
类的对象,把FutureTask
对象作为构造方法的参数 - 启动线程
单线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;
public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException { Run r = new Run(); FutureTask<String> ft = new FutureTask<>(r); Thread thread = new Thread(ft); thread.start(); System.out.println(ft.get()); } }
class Run implements Callable<String> { @Override public String call() throws Exception {
for (int i = 0; i < 100; i++) { System.out.println(i); } return "执行完毕"; } }
|
注意:ft.get()
不可在thread.start()
之前运行
多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;
public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException { Run r1 = new Run(); FutureTask<String> ft1 = new FutureTask<>(r1); Thread thread1 = new Thread(ft1);
Run r2 = new Run(); FutureTask<String> ft2 = new FutureTask<>(r2); Thread thread2 = new Thread(ft2);
thread1.start(); thread2.start(); System.out.println(ft1.get()); System.out.println(ft2.get()); } }
class Run implements Callable<String> { @Override public String call() throws Exception {
for (int i = 0; i < 100; i++) { System.out.println(i); } return "执行完毕"; } }
|
三种实现方式
类型 | 优点 | 缺点 |
---|
实现类 | 扩展性强,实现该接口的同时开可以继承其他的类 | 变成相对复杂,不能直接使用Thread类中的方法 |
继承类 | 编程比较简单,可以直接使用Thread类中的方法 | 可扩展性较差,不能在继承其他的类 |