匿名内部类的几大作用:
1.完成接口实现关系 / 完成类继承关系
2.方法重写
3.创建对象
而Lambda表达式的作用:主要用于实现函数式接口,即用于实现单一抽象方法接口。
所以可以用Lambda表达式实现的函数式接口都可以转换成匿名内部类的形式。
方式一
Thread t = new Thread(){ //匿名内部类
public void run(){
pong();
}
};
在这种方式中,你直接扩展(继承)了Thread类,并重写了它的run方法。然后,你创建了这个匿名内部类的一个实例,并将其赋值给Thread类型的变量t。当你调用t.start()时(虽然在你的代码示例中没有显示调用start(),但通常这是启动线程的方式),JVM会为这个线程分配资源,并调用你重写的run方法。
方式二
Thread t = new Thread(new Runnable() { //匿名内部类
@Override
public void run() {
pong();
}
});
在这种方式中,你并没有直接扩展Thread类,而是创建了一个实现了Runnable接口的匿名内部类的实例。这个匿名内部类实现了Runnable接口的run方法。然后,你创建了一个Thread类的实例,将你的Runnable实例作为参数传递给Thread的构造函数。当你调用t.start()时,JVM同样会为这个线程分配资源,但这次它会调用你传递给Thread构造函数的Runnable实例的run方法。
Lambda表达式
Thread t1 = new Thread(() -> {
pong();
});
这个Lambda表达式是通过实现Runnable接口(特别是实现其run方法)来转换以创建线程的。这是创建线程时使用的方式二。
两者区别
- 继承与实现:第一种方式通过继承Thread类来创建线程,而第二种方式通过实现Runnable接口来创建线程。通常,如果你不需要扩展Thread类(因为Java不支持多重继承),或者你的类已经继承了另一个类,那么实现Runnable接口是更好的选择。
- 灵活性:实现Runnable接口提供了更多的灵活性,因为你可以让你的类实现多个接口,但只能继承一个类。
- 资源共享:在Java中,每个线程都有其执行上下文,包括一组输入/输出流和错误流。当你继承Thread类时,这些资源会自动与你的线程关联。然而,如果你实现Runnable接口,则不会自动获得这些资源,但你可以通过其他方式(如传递参数)来共享这些资源。
- 线程池:当你使用Runnable接口时,可以更容易地将任务提交给线程池执行,因为ExecutorService接口要求提交Runnable或Callable任务,而不是Thread实例。
总的来说,虽然这两种方式在功能上是等价的,但在实际开发中,实现Runnable接口通常是更受欢迎的选择,因为它提供了更多的灵活性和与Java并发API的兼容性。
标签:Runnable,run,Thread,接口,匿名,线程,Lambda From: https://blog.csdn.net/m0_73753865/article/details/143716323