文章目录
- 什么是多线程
- 多线程 三种 实现方法
- 继承 Thread 的方法
- 实现 Runnable接口 的方法
- 实现 Callable接口 并利用 FutureTask类 来接收返回值 的方法
- 我的理解 和 总结
什么是多线程
简单理解:进程就是一个运行的软件,而线程是软件中的一个功能,多个功能就组成了多线程。
作用:提高了运行效率。
多线程 三种 实现方法
继承 Thread 的方法
- 自定义类继承 Thread 重写run方法
- new子类,然后调用 start() 方法,启动线程
- 对象setName(“线程1”) 可以设置线程名字,在类中可以用getName() 来获取
例子:
package com.study;
// 自定义类继承 Thread
public class MyThread extends Thread{
// 重写run方法
@Override
public void run() {
super.run();
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ": helloworld");
}
}
}
package com.study;
public class ThreadDemo {
public static void main(String[] args) {
// new子类
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
// 设置线程名字
t1.setName("线程1");
t2.setName("线程2");
// 调用 start() 方法,启动线程
t1.start();
t2.start();
}
}
运行截图:
实现 Runnable接口 的方法
- 定义一个类实现Runnable接口
- 重写run方法
- 创建自己的类对象
- 创建Thread对象,开启线程
注意:也可以setName,但是要记住,这种方法,类中不能直接使用getName方法,因为并没有继承Thread,自然类中没有此方法。但是可以在类中获取当前正在运行线程的对象,来获取name。
例子:
package com.study.threaddemo2;
// 定义一个类实现Runnable接口
public class MyRun implements Runnable{
// 重写run方法
@Override
public void run() {
for (int i = 0; i < 100; i++) {
Thread h = Thread.currentThread(); // 获取当前线程的对象
System.out.println(h.getName() + ":helloworld");
}
}
}
package com.study.threaddemo2;
public class Test2 {
public static void main(String[] args) {
// 创建自己的类对象
MyRun r1 = new MyRun();
MyRun r2 = new MyRun();
// 创建Thread对象
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
// 设置线程名字
t1.setName("线程1");
t2.setName("线程2");
// 开启线程
t1.start();
t2.start();
}
}
运行截图:
实现 Callable接口 并利用 FutureTask类 来接收返回值 的方法
- 实现Callable接口
- 重写call方法,有返回值
- 创建自己类的对象
- 创建FutureTask对象(管理多线程运行结果)
- 创建Thread类对象且启动
注意:Callable泛型,填入返回的类型。
例子:
package com.study.threaddemo3;
import java.util.concurrent.Callable;
// 实现Callable接口
public class MyCallable implements Callable<Integer> {
// 重写call方法
public Integer call() {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
return sum;
}
}
package com.study.threaddemo3;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建自己类的对象
MyCallable mc = new MyCallable();
// 创建FutureTask对象
FutureTask<Integer> ft = new FutureTask<>(mc);
// 创建Thread类对象且启动
Thread t1 = new Thread(ft);
t1.start();
// 获取返回值
Integer res = ft.get();
System.out.println(res);
}
}
运行结果:
我的理解 和 总结
继承Thread类 的方法,实际就是自己创建了一个流水线,并同时创建了任务,也就是流水线运输和处理的内容。 自然我们可以在流水线中知道此流水线的名字。
实现Runnable接口 的方法,实际是创建了一个任务,我们还需要创建流水线,去运行此任务。 我们不能根据任务就知道运行此任务的流水线名字,因为可能有多个流水线执行此任务,所以我们要先获取正在执行此任务的流水线,这样就能知道正在运行的流水线名了,因为并发只能有一条流水线正在运行。
实现Callable接口 的方法,此方法就可以用FutureTask这个员工来获得流水线处理任务后的结果(返回值),弥补了上面两种方法的不足。
这样解释是不是很好理解呢?当然这只是通俗的解释一下,方便理解,具体原理肯定还是要看代码的。
可以根据每种方法的优缺点来进行选择使用。