简体   繁体   English

Java 线程:如何为线程实现可运行的工作

[英]Java Threading: How does implementing runnable work for threading

I understand that if you want to thread you can either extend thread or implement runnable to multithread in java.我知道如果你想要线程,你可以扩展线程或在 java 中实现可运行到多线程。 But why do you have to implement an interface for java to thread?但是为什么非要实现一个接口让java去线程呢? Whats the importances of the runnable interface that makes java threading work?使 Java 线程工作的可运行接口的重要性是什么? Does Java's interface extend from something? Java 的接口是否从某物扩展而来?

The only thing special about the Runnable interface is that it is what Thread takes in its constructor. Runnable接口的唯一特殊之处在于它是Thread在其构造函数中采用的内容。 It's just a plain-old interface.它只是一个普通的旧界面。

As with most interfaces, the point is that you're programming to a contract: you agree to put the code you want to run in the Runnable#run() implementation, and Thread agrees to run that code in another thread (when you create and start a Thread with it).与大多数接口一样,关键是您正在根据合同进行编程:您同意将要运行的代码放在Runnable#run()实现中,并且Thread同意在另一个线程中运行该代码(当您创建并用它启动一个Thread )。

It's Thread that actually "does" the multithreading (in that it interacts with the native system).实际上“执行”多Thread处理的是线程(因为它与本机系统交互)。 An implementation of Runnable is just where you put the code that you want to tell a Thread to run. Runnable的实现就是放置要告诉Thread运行的代码的地方。

In fact, you can implement a Runnable and run it, without having it run in a separate thread:事实上,您可以实现一个Runnable并运行它,而无需让它在单独的线程中运行:

Runnable someCode = new Runnable() {
    public void run() {
       System.out.println("I'm a runnable");
    }
};
someCode.run();

So Runnable itself doesn't have anything to do with multi-threading, it's just a standard interface to extend when encapsulating a block of code in an object.所以Runnable本身与多线程没有任何关系,它只是在对象中封装一段代码时扩展的标准接口。

In terms of functionality, there is no difference between implementing Runnable interface or extending Thread class.在功能上,实现Runnable接口和扩展Thread类没有区别。 But there might be situations that implementing Runnable interface could be preferred.但是在某些情况下,可能更喜欢实现Runnable接口。 Think of the case that your class has to inherit from some other class and also it should show thread functionality.考虑一下您的类必须从其他类继承的情况,并且它还应该显示线程功能。 Since your class cannot inherit from multiple classes(Java doesn't support it), your class could implement Runnable interface in that case.由于您的类不能从多个类继承(Java 不支持),因此在这种情况下您的类可以实现Runnable接口。

But why do you have to implement an interface for java to thread?但是为什么非要实现一个接口让java去线程呢?

You don't, as you said previously you can extend the Thread object and implement a public void run method.您不需要,正如您之前所说,您可以扩展 Thread 对象并实现 public void run 方法。 If you want a more organized and flexible (yes, flexible) approach you definitely want to use Runnable for an obvious reason: Code reusability.如果你想要一种更有条理和灵活(是的,灵活)的方法,你肯定想要使用 Runnable,原因很明显:代码可重用性。

When I say organized, I want to say that it's easy to maintain a当我说有条理时,我想说的是维护一个

Runnable doSomething = new Runnable()
{
    @Override
    public void run()
    {
        goAndDoSomethingReallyHeavyWork();
    }
};

and then reuse the same runnable for another thread, or the same thread in another moment (yes, you can actually re-use a Thread) than extend 2 or more threads into objects that you will use once.然后为另一个线程重用相同的可运行对象,或者在另一时刻重用同一个线程(是的,您实际上可以重用一个线程),而不是将 2 个或更多线程扩展到您将使用一次的对象中。

Whats the importances of the runnable interface that makes java threading work?使 Java 线程工作的可运行接口的重要性是什么?

The importance is that the Thread object will "know" that your Runnable has a method run and will execute it when it have to (and so stop, pause and other Thread actions).重要的是 Thread 对象将“知道”您的 Runnable 有一个方法 run 并在必须时执行它(因此停止、暂停和其他 Thread 操作)。

Does Java's interface extend from something? Java 的接口是否从某物扩展而来?

This question is worth my +1 to you.这个问题值得我 +1 给你。 I would really like to know, but it seems it's a feature of the language and not a product of itself like every other object that extends the Object super class.我真的很想知道,但它似乎是语言的一个特性,而不是像扩展 Object 超类的每个其他对象一样本身的产物。

I hope it helped.我希望它有所帮助。 Cheers干杯

But why do you have to implement an interface for java to thread?但是为什么非要实现一个接口让java去线程呢?

When you create a thread extending class Thread, You can no more extend any other class(multiple inheritance).当您创建一个线程扩展类 Thread 时,您不能再扩展任何其他类(多重继承)。 On the other hand, If you use Runnable,you get the inheritance benefits of extending any class, if needed.另一方面,如果您使用 Runnable,如果需要,您可以获得扩展任何类的继承优势。

In addition to above you also get memory and performance level benefits.除了上述之外,您还可以获得内存和性能级别的好处。

ExecutorService.submit( Runnable task )

You said:你说:

extend thread延长线程

We no longer need to directly address the Thread class to run code concurrently.我们不再需要直接访问Thread类来并发运行代码。 Java 5 introduced the Executors framework. Java 5引入了 Executors 框架。 See tutorial by Oracle .请参阅Oracle 的教程

An executor service manages running your tasks on one or more background threads.执行程序服务管理在一个或多个后台线程上运行您的任务。 You can choose from several types of executor services, instantiated via the Executors class.您可以从几种类型的执行程序服务中进行选择,这些服务通过Executors类实例化。

For an occasional few short-lived tasks, use an executor service backed by a cached thread pool.对于偶尔出现的一些短期任务,请使用由缓存线程池支持的执行程序服务。

ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit( yourRunnableObjectGoesHere ) ;

The job of an ExecutorService is to execute the code in a method named exactly run or call . ExecutorService的工作是执行名为runcall的方法中的代码。

As other correct Answers explained, the purpose of the Runnable interface is that it represents a contract.正如其他正确答案所解释的那样, Runnable接口的目的是它代表一个合同。 When your code claims to implement the Runnable interface, you are promising that your code has a method named exactly run .当您的代码声称实现Runnable接口时,您承诺您的代码有一个名为run的方法。

The Java compiler notices this promise and checks to see that the contract is fulfilled. Java 编译器注意到这个承诺并检查合同是否已履行。 If you pass an object that fails to both (a) declare that it implements Runnable , and (b) carries a method run that takes no arguments and returns no value, then the compiler flags that situation as an error.如果您传递的对象未能同时 (a) 声明它实现Runnable并且(b) 携带不带参数且不返回任何值的方法run ,则编译器会将这种情况标记为错误。

So an executor service requires that you submit your task as an object of a class that implements the Runnable (or Callable ) interface to guarantee that when a task arrives to be executed on a background thread, that task has a method named exactly run (or call for Callable ).因此,执行程序服务要求您将任务作为实现Runnable (或Callable )接口的类的对象提交,以保证当任务到达并在后台线程上执行时,该任务有一个名为run (或call Callable )。

Sample code示例代码

Here is some example code.这是一些示例代码。 Notice how the executor service does not care what kind object you pass to its submit method.请注意执行程序服务如何不关心您传递给它的submit方法的对象类型。 You could pass an object of the class Dog , SalesReport , or Payroll — does not matter.您可以传递类DogSalesReportPayroll的对象——都没有关系。 All the executor service cares about is that the object passed to submit has a method called run . executor 服务只关心传递给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() );
        }
    }
}

When run:运行时:

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

Lambda syntax Lambda 语法

If you are comfortable with lambda syntax in modern Java, we can shorten to a single line that code defining your Runnable implementation.如果您熟悉现代 Java 中的 lambda 语法,我们可以将其缩短为定义Runnable实现的代码行。 Same effect, just different syntax.效果一样,只是语法不同。

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() );
        }
    }
}

Inheritance遗产

You asked:您询问:

Does Java's interface extend from something? Java 的接口是否从某物扩展而来?

All classes in Java extend either the Object class or some other class that extends from Object . Java 中的所有类都扩展了Object类或从Object扩展的其他类。

An interface in Java does not extend from any class. Java 中的接口不从任何类扩展。 Remember that an interface is just a contract, a promise that some class may choose to make with regard to having methods with particular names that takes certain types of arguments and return a certain type of value.请记住,接口只是一个契约,一些类可能选择做出关于具有特定名称的方法的承诺,这些方法接受特定类型的参数并返回特定类型的值。

An interface in Java can extend one or more other interfaces. Java 中的接口可以扩展一个或多个其他接口。 Doing so just adds more methods to the promise being made by a class claiming to implement that interface.这样做只会为声称实现该接口的类所做的承诺添加更多方法。 Notice that Runnable is extended by two other interfaces: RunnableFuture and RunnableScheduledFuture .请注意, Runnable由另外两个接口扩展: RunnableFutureRunnableScheduledFuture

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM