1.什么是多线程?
首先我们要了解什么是线程?
简单来说,有了多线程,我们就可以让程序同时做多件事 可以提高程序的效率 应用场景也非常广泛 比如:软件中的耗时操作、所有的聊天软件和服务器
多线程涉及并发和并行
并发:在同一时刻,有多个指令在单个cpu上交替执行
并行:在同一个时刻,有多个指令在多个cpu上同时执行
2.多线程有三种启动方式:
-
继承Thread类的方式进行实现
-
步骤:
- 自己定义一个类继承Thread
- 重写run方法
- 创建子类对象,并启动线程
代码演示:
package ThreadDome;
public class th01 extends Thread {
/*
多线程的一种启动方式
1.自己定义一个类继承Thread
2.重写run方法
3.创建子类对象,并启动线程
*/
//2.重写run方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"Hello Wrold!");
}
}
}
class th01Test {
public static void main(String[] args) {
//3.创建子类对象
th01 t1=new th01();
th01 t2=new th01();
//给线程命名
t1.setName("线程1");
t2.setName("线程2");
//启动多线程
t1.start();
t2.start();
}
}
-
实现Runnable接口的方式进行实现
-
步骤:
- 自己定义一个类实现Runnable接口
- 重写里面的run方法
- 创建自己的实现类
- 创建Thread对象,并开启线程
代码演示:
public class MyRun implements Runnable{
//线程的第二种方式,创建Runnable接口的实现类
@Override
public void run() {
//在run方法里面写入要执行的代码
//获取当前线程的对象
Thread t = Thread.currentThread();
for (int i = 0; i < 100; i++) {
System.out.println(t.getName()+"Hello World!");
}
}
}
class MyRunTest {
/*
* 创建线程的第二种方式:
* 1.自己定义一个类实现Runnable接口
* 2.重写里面的run方法
* 3.创建自己的实现类
* 4.创建Thread对象,并开启线程
*/
public static void main(String[] args) {
//1.创建自己的实现类
MyRun mr=new MyRun();
//2.创建Thread对象,并开启线程
Thread t1=new Thread(mr);
Thread t2=new Thread(mr);
//3.给线程命名
t1.setName("线程1");
t2.setName("线程2");
//4.开启线程
t1.start();
t2.start();
}
}
-
利用Callable接口和Futrue接口方式实现
-
步骤
- 创建一个类MyCallable实现Callable接口
- 重写call()方法 返回值:表示多线程运行的结果
- 创建MyCallable实现类的对象,表示多线程要执行的任务
- 创建FutrureTask对象,作用管理多线程运行的结果
- 创建Thread对象,并启动,表示线程
代码演示:
package ThreadDome;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
//写入要执行的代码
//求1-100的和
int sum=0;
for (int i = 0; i <= 100; i++) {
sum+=i;
}
return sum;
}
}
class MyCallableTest{
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*
多线程的第三种实现方式
特点:可以获取到多线程运行的结果
//
1.创建一个类MyCallable实现Callable接口
2.重写call()方法 返回值:表示多线程运行的结果
3.创建MyCallable实现类的对象,表示多线程要执行的任务
4.创建FutrureTask对象,作用管理多线程运行的结果
5.创建Thread对象,并启动,表示线程
*/
//1.创建MyCallable实现类的对象,表示多线程要执行的任务
MyCallable mc=new MyCallable();
//2.创建FutrureTask对象,作用管理多线程运行的结果
FutureTask<Integer> ft=new FutureTask<>(mc);
//3.创建Thread对象,并启动,表示线程
Thread t=new Thread(ft);
//4.启动线程
t.start();
//获取call方法的返回值
Integer result = ft.get();
System.out.println(result);
}
}
3.多线程三种启动方式的优缺点
优点 | 缺点 | |
继承Thread类 | 编程比较简单,可以直接使用Thread类中的方法 | 可以扩展性较差,不能再继承其他的类 |
实现Runnable接口 | 扩展性强,实现该接口的同时还可以继承其他的类 | 编程相对复杂,不能直接使用Thread类中的方法 |
实现Callable接口 | 扩展性强,实现该接口的同时还可以继承其他的类 | 编程相对复杂,不能直接使用Thread类中的方法 |
总结:前面两种不可以获取多线程运行的结果 最后一种是可以获取多线程运行结果的,有返回值。实现Runnable接口和实现Callable接口优缺点差不多