一、继承Thread类
基础方法:
- 自定义线程类继承Thread类
- 重写run()方法,编写线程执行方法体
- 创建线程对象,调用start()方法启动线程
代码样例:
public class Demo {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread1 thread1 = new Thread1(); //创建线程对象
thread1.start(); //开启线程,执行run方法
}
System.out.println("主线程执行了!");
}
}
class Thread1 extends Thread{
@Override
public void run() { //重写run()方法,编写线程执行方法体
System.out.println(Thread.currentThread().getName()+"线程执行了");
}
}
拓展:
-
线程调用run方法和start方法的区别:
run方法:多线程存储程序的地方,和类的方法调用没有本质区别,如果线程调用run方法启动,则还是主线程执行方法。
- 执行结果:
start方法:开启线程,同时,调用run方法。此时线程自身抢占CPU执行run方法,顺序不定。
- 执行结果:
-
Thread类实现了Runnable函数式接口,其中的run方法就是重写Runnable中的run方法。
-
不建议使用:避免OOP单继承局限性
二、实现Runable接口
基础方法:
- 自定义线程类实现Runnable接口
- 创建Runnable接口实现类对象
- 创建线程Thread对象,通过线程对象开启代理
- 调用start()方法启动线程
代码样例:
public class Demo2 {
public static void main(String[] args) {
Runnable runnable = new Thread2();//创建Runnable接口实现类对象
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(runnable);//创建线程Thread对象,通过线程对象开启代理
thread.start();
}
System.out.println("主线程执行了!");
}
}
class Thread2 implements Runnable{//自定义线程类实现Runnable接口
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程执行了");
}
}
拓展:
-
Thread类是实现Runable接口的一个代理对象。
-
推荐使用:避免单继承局限性,灵活方便,一个对象多个线程使用
-
lambda表达式:
由于Runable是一个函数式接口
public interface Runnable { public abstract void run(); //只含有一个抽象方法的接口叫做函数式接口 }
JDK1.8新特性lambda表达式可以使用。不用new一个新的对象而直接用直接用()->{};
public class Demo2 { public static void main(String[] args) { for (int i = 0; i < 5; i++) { Thread thread = new Thread(()->{ System.out.println(Thread.currentThread().getName()+"执行了!"); });//lambda表达式 thread.start(); } System.out.println("主线程执行了!"); } }
三、Callable
基础方法:
代码样例:
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
FutureTask<String> futureTask = new FutureTask<>(myThread);//创建futureTask对象,搭载出runable和callable的联系,
new Thread(futureTask).start();//启动线程
String s = futureTask.get();//接受callable的返回值,可能会产生阻塞
System.out.println(s);
}
}
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("111");
return "1234";
}
}
拓展:
-
与Runable的不同点:
- 可以有返回值
- 可以抛出异常
- 方法不同,run/call
-
有缓存,多个线程同时工作,只输出一个
-
结果可能需要等待,会阻塞,所以把futureTaks的get方法放在最后执行
-
callable和thread没有直接的联系,我们需要用Runbale作为中间连接人,选择子类对象FutureTask搭载出runable和callable的联系。
public FutureTask(Callable<V> callable) //FutureTask传入callable参数 // public class FutureTask<V> implements RunnableFuture<V> public interface RunnableFuture<V> extends Runnable, Future<V>//FutureTask实现RunnableFuture,RunnableFuture继承Runnable接口