多线程的实现方案:
- 继承 Thread类 的方式实现。
- 实现 Runnable接口 的方式实现。
- 利用 Callable接口 和 Future接口 的方式实现。
方案1:继承Thread类
- 定义一个 MyThread类 继承 Thread类。
- 在 MyThread类 中重写 run()方法。
- 创建 MyThread类 的对象。
- 启动线程。
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程开始了" + i);
}
}
}
public class Demo {
public static void main(String[] args) {
MyThread m1 = new MyThread();
MyThread m2 = new MyThread();
m1.start();
m2.start();
}
}
- 为什么要重写run()方法?
因为run()被用来封装线程需要执行的代码。
- run()方法和start()方法的区别?
run()表示的仅仅是创建对象,调用对象的方法,并没有开启线程。
start()表示与系统资源进行交互,开启一条线程。
方法二:实现Runnable接口
- 定义一个MyRunnable类实现Runnable接口。
- 在MyRunnable类中重写run()方法。
- 创建MyRunnable类的对象。
- 创建Thread类的对象,并把MyRunnable类的对象作为构造方法的参数传入。
- 启动线程。
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("第二种方法实现多线程" + i);
}
}
}
public class Demo {
public static void main(String[] args) {
MyRunnable mr1 = new MyRunnable();//创建了一个参数的对象。
Thread t1 = new Thread(mr1);//创建了一个线程对象,并把参数传递给这个线程。
t1.start();//在线程启动之后执行的是参数里面的run()方法。
MyRunnable mr2 = new MyRunnable();
Thread t2 = new Thread(mr2);
t2.start();
}
}
方式三:实现Callable接口和Future接口
- 定义MyCallable类实现Callable接口。
- 在MyCallable类中重写call()方法。
- 创建MyCallable类的对象
- 创建 Future类 的实现类 FutureTask类 的对象,把MyCallable类的对象作为构造方法的参数传入。
- 创建Thread类的对象,并把FutureTask对象作为构造方法的参数。
- 启动线程。
//这里的泛型中的数据类型和下面call()方法的返回值类型一致
//想要返回什么数据,就写对应的数据类型
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("第" + i + "次表白");
}
return "I DO.";
}
}
public class Demo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//线程开启后需要执行里面的call()方法
MyCallable mc = new MyCallable();
//好比一个中间媒介
//既可以获取线程执行完毕的结果,也可以作为参数传递给Thread对象。
FutureTask<String> ft = new FutureTask<>(mc);
//创建线程对象
Thread t = new Thread(ft);
//开启线程
t.start();
System.out.println(ft.get());
}
}
FutureTask类既实现了Future接口也实现了Runnable接口,详细可查官方文档,故可以作为参数传入Thread的构造方法。
注意:get()方法要在线程开启之后调用。
三种方式的对比
优点 | 缺点 | ||
---|---|---|---|
实现接口 | 实现Runnable接口(没有返回值) | 扩展性强,实现该接口的同时还可以继承其他的类。 | 编程相对复杂,不能直接使用Thread类中的方法。 |
实现Callable接口(有返回值) | |||
继承Thread类 | 编程比较简单, 可以直接使用Thread类中的方法。 |
可扩展性差, 不能再继承其他的类。
|