java 17 多线程之 Runnable 知识点

上一篇说了 Thread 的基础用法之后, 接下来就说说 Runnable 的相关使用方式。

Runnable 来自模块:java.base 以及包名为:Java.lang

Runnable 接口

先查看一下该接口的定义:

@FunctionalInterface public interface Runnable

并且该接口就一个方法 run

public abstract void run();

根据 Java 17 的 API 可以得知,Runnable 接口由其实现类来由线程执行对应的实例。对于实现类必须是实现方法 run。

该接口旨在为希望在它们处于活动状态时执行代码的对象提供一个通用协议。 例如,Runnable 是由类 Thread 实现的。 处于活动状态仅意味着线程已启动且尚未停止。

此外,Runnable 提供了使类处于活动状态而不需要继承 Thread 的重载方法。 对于实现 Runnable 的子类, 只需要传入对应的实现到 Thread 实例中, 就可以直接运行, 而不需要再进行 Thread 的基础上继承实现 run 方法。 所以,如果你不需要修改或者增强 Threa 类的基本行为,则应该使用 Runnable 接口。

方法说明

修饰符和类型

方法

描述

void

run()

当使用实现接口 Runnable 的对象创建线程时,启动线程会导致在该单独执行的线程中调用对象的 run 方法。

它只是实现了线程需要执行的内容,但是启动线程还是需要 Thread 的启动。使用方法 Thread.start() 方法。这个上一节已经详细的说过这个。

接口实现的方式

一般情况下有三种方式使用: 1. 匿名实现类。2. 外部实现类。3. 函数接口 Lambda 表达式。

匿名实现类

代码如下:

Runnable runnable = new Runnable() { @Override public void run() { System.out.println("runnable 匿名类"); } }; Thread thread = new Thread(runnable); thread.start();

完整代码和演示效果:

java多线程知识点(Java17多线程之)(1)

外部实现类

先定义个实现类:

class MyRunnable implements Runnable { @Override public void run() { System.out.println("实现 Runnable 接口的 run() 方法。"); } }

然后调用该实现类, 完整代码以及运行效果如下:

java多线程知识点(Java17多线程之)(2)

函数接口 Lambda

代码如下:

Thread threadLambda = new Thread(()->{ System.out.println("Lambda 表达式的写法,执行完毕"); }); threadLambda.start(); System.out.println("main 执行完毕");

最简单的调用方式演示:

java多线程知识点(Java17多线程之)(3)

如果对于 Lambda 表达式还不熟悉,可以查看我之前写的 Lambda 的知识点。应该是比较详细且简单。这个在全栈中还是比较有复用的知识点,前端,Java,Python 以及其他的很多语言中都支持该语法糖,并且使用起来更加方便。

除了这些用法之外,还有上一章少讲了的知识点。 对于 Thread.yield() 方法的使用。

Thread threadLambda = new Thread(()->{ long startTime = System.currentTimeMillis(); System.out.println("演示 yield 方法的使用。"); long count = 0; for (int i = 0; i < 5000000; i ) { count = count i; Thread.yield(); } long endTime = System.currentTimeMillis(); System.out.println("包含总用时: " (endTime - startTime) " 毫秒"); }); threadLambda.start();

注释掉 Thread.yield(); 方法。再次测试。查看其使用的时间。

java多线程知识点(Java17多线程之)(4)

yield 方法主要是放弃当前的 CPU 资源,让其他的任务占用 CPU 执行的时间,在放弃的时候,放弃的时间是不确定的,并且放弃之后,重新获取 CPU 时间片的时间也不确定, 有可能刚刚放弃就又分配 CPU 的时间片。

根据上面的案例也能看出来,主动放弃的方式,需要更长的时间来执行 for 循环。 500 万次循环不放弃的情况下使用了 4 毫秒, 放弃的使用了 2644 毫秒。差别还是很大的。在 C/S 开发中这个方法还可以刷新 UI 卡顿的响应效果。已经忘记具体的怎么实现了,不知道现在有没有新的解决方案。 太长时间没有开发桌面程序了。 忘记的差不多了。虽然已经忘记了具体的知识点,但是一样能够想起来有这个知识点。这就是学习的意义吧。虽然学着会忘记,但是学习过的内容都会成为你记忆的一部分,等待着汇集到最后的灵光一现,升级成功。

感谢您的阅读,这节知识点太少。最近忙着项目的事情,更新频率下降了不少。希望更合理的安排时间。毕竟杂事是最浪费时间的。

点赞,收藏加关注。 持续技术知识输出。

,