持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
大家好,我是尚影嫣🌷,一名Java后端程序媛。如果您喜欢我的文章,欢迎点赞➕关注❤️,让我们一起成为更好的我们~🥰
多线程的实现方式
使用实现多线程有四种方式:
- 继承Thread类;
- 实现Runnable接口;
- 使用Callable和FutureTask实现有返回值的多线程;
- 使用ExecutorService和Executors工具类实现线程池(如果需要线程的返回值,需要在线程中实现Callable和Future接口)
线程池ExecutorService和工具类Executors优点:可以根据实际情况创建线程数量,且只需要创建一个线程池即可,也能够通过Callable和Future接口得到线程的返回值,程序的执行时间与线程的数量紧密相关。缺点:需要手动销毁该线程池(调用shutdown方法)。
(一) 继承Thread类
继承Thread类的优点:简单,且只需要实现父类的run方法即可(start方法中含有run方法,会创建一个新的线程,而run是执行当前线程)。缺点是:Java的单继承,如果对象已经继承了其他的类则不能使用该方法。且不能获取线程的返回值
package yanf.thread;
public class MyThread extends Thread {
/**
* run方法里面是线程要执行的任务方法
*/
@Override
public void run() {
// 这里的代码是一条新的执行路径
// 这个执行路径的触发方法,不是调用run(),而是调用thread对象的start()来启动任务
for (int i = 0; i < 10; i++) {
System.out.println("锄禾日当午 " + i);
}
}
}
(二) 实现Runnable 接口
实现Runnable接口优点:简单,实现Runnable接口必须实现run方法。缺点:创建一个线程就必须创建一个Runnable的实现类,且不能获取线程的返CallabTask优点:可以获取多线程的返回值。缺点:每个多线程都需要创建一个Callable的实现类。
package yanf.thread;
/**
* 用于给线程进行执行的任务
*/
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+",runnable---"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("发现了中断标记,我们这个线程自杀掉");
return;
}
}
}
}
(三) 通过Callable和FutureTask创建线程
package yanf.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 1. 创建callable对象
Callable<Integer> call = new MyCallable();
// 2. 创建任务
FutureTask<Integer> task = new FutureTask<>(call);
// 判断子线程是否执行完毕
// task.isDone();
// 断子线程没执行完毕也可以取消掉
// task.cancel(true);
// 3. 启动线程
new Thread(task).start();
// 调用了get()方法,主线程会等待子线程执行完成的结果
Integer integer = task.get();
System.out.println("返回值是:" + integer);
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
static class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
return 100;
}
}
}