据我所知,如果你想要线程,你可以在java中扩展线程或实现runnable到multithread。但为什么你必须实现java的接口线程?什么是可运行的接口的重要性,使java线程工作? Java的界面是否扩展了什么?
答案 0 :(得分:10)
Runnable
接口唯一特别之处在于它是Thread
在其构造函数中所采用的内容。这只是一个简单的界面。
与大多数接口一样,重点在于您正在编写合同:您同意将要运行的代码放在Runnable#run()
实现中,Thread
同意运行该代码在另一个线程中(当你使用它创建并启动Thread
时)。
实际上“执行”多线程的Thread
(因为它与本机系统交互)。 Runnable
的实现就是您放置要告诉Thread
运行的代码的位置。
实际上,您可以实现Runnable
并运行它,而不必在单独的线程中运行:
Runnable someCode = new Runnable() {
public void run() {
System.out.println("I'm a runnable");
}
};
someCode.run();
所以Runnable
本身与多线程无关,它只是在对象中封装代码块时扩展的标准接口。
答案 1 :(得分:2)
在功能方面,实现Runnable
接口或扩展Thread
类没有区别。但是可能存在实施Runnable
接口的情况。想想你的类必须从其他类继承而且它应该显示线程功能的情况。由于您的类不能从多个类继承(Java不支持它),因此在这种情况下,您的类可以实现Runnable
接口。
答案 2 :(得分:1)
但是为什么你必须为java实现一个接口线程?
如前所述,您不能扩展Thread对象并实现public void run方法。如果你想要一个更有条理和更灵活(是的,灵活的)方法,你肯定想要使用Runnable一个明显的原因:代码可重用性。
当我说有组织的时候,我想说保持一个
很容易Runnable doSomething = new Runnable()
{
@Override
public void run()
{
goAndDoSomethingReallyHeavyWork();
}
};
然后为另一个线程重用相同的runnable,或者在另一个时刻使用相同的线程(是的,你实际上可以重用一个Thread),而不是将2个或更多个线程扩展到你将使用一次的对象中。
使java线程工作的runnable接口的重要性是什么?
重要的是Thread对象将“知道”Runnable有一个方法运行,并在必要时执行它(因此停止,暂停和其他Thread操作)。
Java的界面是否扩展了什么?
这个问题值得我给你+1。我真的很想知道,但它似乎是语言的一个特性,而不是像扩展Object超类的所有其他对象一样的产品。
我希望它有所帮助。干杯
答案 3 :(得分:0)
但是为什么要为Java线程实现接口呢?
创建线程扩展类Thread时,不能再扩展任何其他类(多重继承)。 另一方面,如果使用Runnable,则可以在需要时获得扩展任何类的继承优势。
除了以上所述,您还可以获得内存和性能级别的好处。
答案 4 :(得分:0)
ExecutorService.submit( Runnable task )
你说:
<块引用>扩展线程
我们不再需要直接寻址 Thread
类来并发运行代码。 Java 5 引入了 Executors 框架。见tutorial by Oracle。
执行程序服务管理在一个或多个后台线程上运行您的任务。您可以从多种类型的执行程序服务中进行选择,这些服务通过 Executors
类进行实例化。
对于偶尔的一些短期任务,请使用由缓存线程池支持的执行程序服务。
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit( yourRunnableObjectGoesHere ) ;
ExecutorService
的工作是在完全命名为 run
或 call
的方法中执行代码。
正如其他正确答案所解释的那样,Runnable
接口的目的是它代表一个合同。当您的代码声称实现 Runnable
接口时,您承诺您的代码具有完全命名为 run
的方法。
Java 编译器注意到此承诺并检查合同是否已履行。如果您传递的对象未能 (a) 声明它实现了 Runnable
,和 (b) 携带一个不接受任何参数且不返回任何值的方法 run
,然后编译器将该情况标记为错误。
因此,执行器服务要求您将任务作为实现Runnable
(或Callable
)接口的类的对象提交,以保证当任务到达时在后台线程上执行,该任务有一个完全命名为 run
(或 call
的 Callable
)的方法。
这是一些示例代码。请注意执行程序服务如何不关心您传递给其 submit
方法的对象类型。您可以传递类 Dog
、SalesReport
或 Payroll
的对象 — 无关紧要。执行器服务只关心传递给 submit
的对象有一个名为 run
的方法。
package work.basil.example;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo
{
public static void main ( String[] args )
{
Demo app = new Demo();
app.demo();
}
private void demo ( )
{
Runnable task = new Runnable()
{
@Override
public void run ( )
{
System.out.println( "Doing this work on a background thread. " + Instant.now() );
}
};
ExecutorService executorService = null;
try
{
executorService = Executors.newCachedThreadPool();
executorService.submit( task );
executorService.submit( task );
executorService.submit( task );
// Wait a moment for the background threads to do their work.
try
{
Thread.sleep( Duration.ofSeconds( 2 ).toMillis() );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
finally
{
if ( Objects.nonNull( executorService ) ) { executorService.shutdown(); }
System.out.println( "Ending the main thread. " + Instant.now() );
}
}
}
运行时:
Doing this work on a background thread. 2020-12-20T07:16:26.119414Z
Doing this work on a background thread. 2020-12-20T07:16:26.119176Z
Doing this work on a background thread. 2020-12-20T07:16:26.119255Z
Ending the main thread. 2020-12-20T07:16:28.124384Z
如果您对现代 Java 中的 lambda 语法感到满意,我们可以将定义您的 Runnable
实现的代码缩短为一行。相同的效果,只是语法不同。
package work.basil.example;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo
{
public static void main ( String[] args )
{
Demo app = new Demo();
app.demo();
}
private void demo ( )
{
Runnable task = ( ) -> System.out.println( "Doing this work on a background thread. " + Instant.now() );
ExecutorService executorService = null;
try
{
executorService = Executors.newCachedThreadPool();
executorService.submit( task );
executorService.submit( task );
executorService.submit( task );
// Wait a moment for the background threads to do their work.
try
{
Thread.sleep( Duration.ofSeconds( 2 ).toMillis() );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
finally
{
if ( Objects.nonNull( executorService ) ) { executorService.shutdown(); }
System.out.println( "Ending the main thread. " + Instant.now() );
}
}
}
你问:
<块引用>Java 的接口是否扩展自某些东西?
Java 中的所有类都扩展 Object
类或从 Object
扩展的其他类。
Java 中的接口不从任何类扩展。请记住,接口只是一个契约,是某个类可能选择做出的承诺,这些方法具有特定名称的方法,这些方法采用特定类型的参数并返回特定类型的值。
Java 中的接口可以扩展一个或多个其他接口。这样做只是为声称实现该接口的类所做的承诺添加了更多方法。请注意,Runnable
由另外两个接口扩展:RunnableFuture
和 RunnableScheduledFuture
。