目录
引入:多线程有哪些实现方式?
- 继承Thread类的方式进行实现
- 实现Runnable接口的方式进行实现
- 利用Callable和Future接口方式实现
一:继承Thread类的方式进行实现
操作步骤:
- 定义一个类MyThread继承Thread类;
- 在MyThread类中重写run()方法;
- 创建MyThread类的对象;
- 启动线程start();
MyThread
public class MyThread extends Thread{
//继承了Thread类,我们就要重写里面的run方法呀,一定要记住啊
//这里需要重写Thread类中的run方法
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println("线程开启了"+i);
}
}
}
public class Demo1 {
public static void main(String[] args) {
//创建线程
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
}
}
我们这里重写run()方法是因为run()用来封装被线程执行的代码。
二:实现Runnable接口的方式进行实现
- 定义一个类MyRunnable实现Runnable接口
- 在MyRunnable类中重写run()方法 -- 线程启动之后执行的任务
- 创建MyRunnable类的对象
- 创建Thread类的对象,把MyRunnable对象作为构造方法的参数,目的:将Runnable接口实现类对象[转换]为Thread类对象,为了调用start()方法开启线程
- 注意:只有Thread类的对象可以调用start()方法开启线程
- 启动线程
代码实现
public class MyRunnable implements Runnable {
//实现Runnable接口
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
System.out.println("Runnable线程开启了"+i);
}
}
}
public class Demo {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
Thread t3 = new Thread(mr);
Thread t4 = new Thread(mr);
//只有Thread类能够调用start()开启线程
t1.start();
t2.start();
t3.start();
t4.start();
}
}
三:实现Callable接口
操作步骤:
- 定义一个类MyCallable实现Callable<方法返回值类型>接口
- 在MyCallable类中重写[call()]方法,注意:call方法是有返回值的,返回值类型和实现Callable接口泛型类型一致
- 创建MyCallable类的对象
- 创建Future的实现类FutureTask对象, 把MyCallable对象作为构造方法的参数。注意:Thread类构造只能接受Runnable实现类对象,不能接受Callable实现类对象。需要转换,转换成FutureTask对象,因为FutureTask实现类Runnable接口同时,FutureTask对象可以调用get()方法获取线程执行之后的结果--将Callable类型转换为FutureTask。
- 创建Thread类的对象,把FutureTask对象作为构造方法的参数--将FutureTask类型转换为Thread
- 启动线程,调用Thread类的start()
- 调用get方法,获取线程结束之后的结果;注意:get()方法是阻塞方法,如果没有开启线程或者线程没有执行完毕,此时调用get()方法会阻塞(一直等)等线程执行完毕,获取结果。
- 注意:一定要先开启线程执行call(),再调用get()
代码实现:
MyCallable
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("抱了女神"+i+"次");
}
//返回值表示线程运行完毕后的结果
return "女神给我一巴掌";
}
}
测试类:Demo
public class Demo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//Thread构造中只能接收Runnable
//需要将Callable转化成为Thread构造中只能接收Runnable,再传递给Thread
MyCallable mc = new MyCallable();
//可以获取线程执行完毕之后的结果,也可以作为参数传递给Thread对象
FutureTask<String> ft = new FutureTask<>(mc);
Thread t1 = new Thread(ft);
t1.start();//只有Thread可以start()开启线程
String s = ft.get();//get方法一定要在start方法之后才能使用,先开线程再获取结果
System.out.println(s);
//此时重复使用同一个FutureTask ---- 同一个任务,任务执行完毕,拿到结果之后
//下一个线程,再使用同一个任务,只能得到结果
//想要重复实行这任务,需要创建新的FutureTask
FutureTask<String> ft2 = new FutureTask<>(mc);
Thread t2 = new Thread(ft2);
t2.start();
String s1 = ft2.get();
System.out.println(s1);
}
}