将Thread对象作为Runnable对象使用的结果

本文探讨了在使用ExecutorService时,提交Runnable任务而非Thread对象的原因。详细解释了使用Thread对象作为任务提交给ExecutorService时存在的问题及额外开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

review一段代码,发现一个程序员在提交途任务给ExexutorService时,任务并不是实现Runnable接口而是继承Thread。

让其优化,竟然说Thread也是实现Runnable,父类(接口)能使用的地方子类肯定也能使用。

理论没有错,能使用但并不代表适用,应该使用Runnable时直接给一个Thread,结果真的一样吗?

Runnable仅仅是一个接口,其中只要你实现run方法,它并不有更多的逻辑,你的Runnable提交给ExexutorService它只会找一个已经存在的线程来执行

run中的代码逻辑,和生产者消费都模式没有多大区别。但是如果你每次提交Thread对象,虽然它的作用仅仅是作为Runnable的run方法被调用,并不会

新分配线程,但是构造Thread对象的成本是非常大的,n多的上下文,安全检查,线程栈的分配。特别是安全性检查,你可以跟进去看它执行了一大砣一大

砣的逻辑,但最后,你并不把它作为线程来运行,你只要run方法中的代码交给ExexutorService中的其它线程来运行,这种overhead的开销,很多时候比

run中的执行逻辑还大。


所以该用Runnable的时候,千万不要把Thread传进去。

<think>好的,用户的问题是关于Java中通过Thread(Runnable target, String name)构造函数创建的线程对象为何不能调用某些方法。首先,我需要理解用户的具体疑惑点。用户可能在使用这个构造函数创建线程后,尝试调用某些方法时遇到了问题,比如无法调用Runnable接口中的方法,或者某些Thread类的方法不可用。 首先,我应该回顾一下Java中ThreadRunnable的关系。Thread类本身实现了Runnable接口,所以当使用Runnable target的构造函数时,实际上是将target作为线程执行的任务。当线程启动时,会调用target的run方法,而不是Thread类本身的run方法,除非子类覆盖了它。 接下来,用户提到的无法调用某些方法,可能是因为他们混淆了Thread对象Runnable对象的方法。例如,Runnable接口只有一个run()方法,而Thread类有其他方法如start()、join()等。如果用户尝试在Runnable实例上调用Thread特有的方法,这显然是不行的,因为Runnable没有这些方法。 另外,用户可能没有正确理解对象引用的类型。例如,如果使用Runnable实例创建了Thread对象,但之后将Thread对象向上转型为Runnable接口类型,那么通过该接口引用只能调用Runnable的方法,无法访问Thread的其他方法。这时候需要向下转型回Thread类型才能调用那些方法,但这并不推荐,因为可能存在类型不匹配的风险。 还需要考虑构造函数的参数问题。Thread(Runnable target, String name)确实接受一个Runnable和一个名称,创建后的Thread对象可以调用start()方法启动线程。但如果用户错误地直接调用run()方法,这并不会启动新线程,而是普通的方法调用,这可能让用户误以为某些方法无效。 此外,用户可能期望在Runnable实现中添加自定义方法,但通过Thread构造函数传入的Runnable实例,其类型是Runnable接口,只能访问接口中定义的方法。如果需要调用额外的方法,必须将实例强制转换为具体的实现类,但这需要确保类型正确,否则会抛出异常。 最后,我需要检查是否有其他可能的原因,比如访问权限问题,或者方法不存在于所使用的Java版本中。但通常来说,常见的问题还是在于对ThreadRunnable的关系理解不透彻,以及引用类型的问题。 总结下来,用户的问题可能源于对线程创建方式、接口与实现类的方法可见性,以及对象引用的类型转换理解不足。需要详细解释ThreadRunnable的关系,并举例说明正确的使用方法和常见的误操作,帮助用户理解为何某些方法不可调用。</think>### 通过 `Thread(Runnable target, String name)` 创建的对象为何无法调用某些方法? 在 Java 中,通过 `Thread(Runnable target, String name)` 构造函数创建的线程对象,其行为与普通 `Thread` 对象类似,但可能因以下原因导致某些方法无法调用: --- #### 1. **方法归属问题** - **`Runnable` 接口的局限性** `Runnable` 接口仅定义了 `run()` 方法,而 `Thread` 类本身实现了 `Runnable` 接口。当通过 `Thread(Runnable target, ...)` 构造函数创建线程时: - 若直接操作 `Runnable` 对象(如 `target`),则只能调用 `run()` 方法。 - 若操作 `Thread` 对象,则可以调用 `start()`、`join()` 等方法。 示例: ```java Runnable task = () -> System.out.println("Running"); Thread thread = new Thread(task, "MyThread"); thread.start(); // 正确:调用 Thread 类的方法 // task.start(); // 错误:Runnable 没有 start() 方法 ``` --- #### 2. **向上转型导致方法不可见** - **引用类型限制** 如果将 `Thread` 对象赋值给 `Runnable` 类型的变量,会丢失对 `Thread` 特有方法的访问权: ```java Runnable runnableRef = new Thread(task, "MyThread"); // runnableRef.start(); // 错误:Runnable 接口没有 start() 方法 ``` 需通过向下转型恢复: ```java if (runnableRef instanceof Thread) { ((Thread) runnableRef).start(); // 可行但不推荐 } ``` --- #### 3. **构造函数与线程生命周期** - **必须通过 `start()` 启动线程** 直接调用 `run()` 方法不会启动新线程,而是同步执行代码: ```java Thread thread = new Thread(task, "MyThread"); thread.run(); // 合法但错误:不会创建新线程 thread.start(); // 正确:启动新线程并执行 run() ``` --- #### 4. **自定义方法的访问限制** 如果 `Runnable` 实现类中定义了额外方法,但通过 `Runnable` 接口引用该对象时,这些方法将不可见: ```java class MyTask implements Runnable { public void run() { /* ... */ } public void customMethod() { /* ... */ } } Runnable task = new MyTask(); Thread thread = new Thread(task, "MyThread"); // task.customMethod(); // 错误:Runnable 接口无此方法 ((MyTask) task).customMethod(); // 可行,但需确保类型匹配 ``` --- #### 5. **线程状态限制** 某些方法(如 `interrupt()`)需在线程处于特定状态时调用。例如,未启动的线程调用 `interrupt()` 可能无效: ```java Thread thread = new Thread(task, "MyThread"); thread.interrupt(); // 无效:线程未运行 ``` --- ### 关键总结 | 场景 | 可调用方法 | 限制原因 | |------|------------|----------| | 通过 `Runnable` 引用操作 | 仅 `run()` | 接口方法限制 | | 通过 `Thread` 引用操作 | `start()`, `join()`, `interrupt()` 等 | 类型可见性 | | 自定义方法 | 需强制类型转换 | 接口抽象性 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值