一 继承Thread类
实现步骤:
定义一个类(MyThread)继承Thread类
在MyThread类中重写run()方法
创建MyThread类的对象
启动线程 (对象名.start();)
1 run()和start()方法的区别
(1) 重写run()方法的原因:
run()是用来封装被线程执行的代码
(2) run()和start()方法的区别:
run():封装线程执行的代码,直接调用,相当于普通方法的调用,并没有开启线程。 (顺序执行)
start():启动线程;然后由JVM调用此线程的run()方法 (交替执行)
- 交替:并不是某一个线程执行完了再执行另外一个线程,也不是ABAB..
是看电脑的内部分配,谁先抢到执行权谁就先执行
二 实现Runnable接口(重点)
实现步骤:
定义一个类(MyRunnable)实现Runnable接口
在MyRunnable类中重写run()方法
创建MyRunnable类的对象
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
启动线程 (对象名.start();)
- 使用自定义类实Runnable接口比继承Thread类更加有优势
类可以多实现(拥有多个接口的功能),但是只能单继承(只能拥有一个类的功能)多实现的拓展性就更强。
三 实现Callable接口(了解)
实现步骤:
定义一个类(MyCallable)实现Callable接口
在MyCallable类中重写call()方法
创建MyCallable类的对象
创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
创建Thread类的对象,把FutureTask对象作为构造方法的参数
启动线程 (Thread类的对象名.start();)
再调用get方法,就可以获取线程结束之后的结果(call方法的返回值)(FutureTask类的对象名.get)
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
return "over";
}
}
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建自定义线程对象
MyCallable mc=new MyCallable();
//创建FutureTask对象(需要传递Callable对象)
FutureTask<String> task=new FutureTask<>(mc);
//创建线程类对象
Thread thread=new Thread(task);
thread.start();
for (int j = 0; j < 100; j++) {
System.out.println("j = " + j);
}
//获取call()方法中的返回值数据
String s = task.get();
System.out.println(s);
}
}
四 三种实现方式对比
实现Runnable、Callable接口:
- 好处:扩展性强,实现该接口的同时还可以继承其他的类
- 缺点:编程相对复杂,不能直接使用Thread类中的方法
继承Thread类:
- 好处:编程简单,可以直接使用Thread类中的方法
- 缺点:扩展性较差,不能在继承其他的类
-