Java Threading: How does implementing runnable work for threading

前端 未结 5 1165
Happy的楠姐
Happy的楠姐 2021-02-10 00:21

I understand that if you want to thread you can either extend thread or implement runnable to multithread in java. But why do you have to implement an interface for java to thre

相关标签:
5条回答
  • 2021-02-10 00:49

    ExecutorService.submit​( Runnable task )

    You said:

    extend thread

    We no longer need to directly address the Thread class to run code concurrently. Java 5 introduced the Executors framework. See tutorial by 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.

    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.

    As other correct Answers explained, the purpose of the Runnable interface is that it represents a contract. When your code claims to implement the Runnable interface, you are promising that your code has a method named exactly run.

    The Java compiler notices this promise and checks to see that the contract is fulfilled. 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.

    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).

    Sample code

    Here is some example code. Notice how the executor service does not care what kind object you pass to its submit method. You could pass an object of the class Dog, SalesReport, or Payroll — does not matter. All the executor service cares about is that the object passed to submit has a method called 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

    If you are comfortable with lambda syntax in modern Java, we can shorten to a single line that code defining your Runnable implementation. 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?

    All classes in Java extend either the Object class or some other class that extends from Object.

    An interface in Java does not extend from any class. 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. 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.

    0 讨论(0)
  • 2021-02-10 00:50

    In terms of functionality, there is no difference between implementing Runnable interface or extending Thread class. But there might be situations that implementing Runnable interface could be preferred. 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.

    0 讨论(0)
  • 2021-02-10 01:08

    The only thing special about the Runnable interface is that it is what Thread takes in its constructor. 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).

    It's Thread that actually "does" the multithreading (in that it interacts with the native system). An implementation of Runnable is just where you put the code that you want to tell a Thread to run.

    In fact, you can implement a Runnable and run it, without having it run in a separate thread:

    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.

    0 讨论(0)
  • 2021-02-10 01:13

    But why do you have to implement an interface for java to thread?

    When you create a thread extending class Thread, You can no more extend any other class(multiple inheritance). On the other hand, If you use Runnable,you get the inheritance benefits of extending any class, if needed.

    In addition to above you also get memory and performance level benefits.

    0 讨论(0)
  • 2021-02-10 01:14

    But why do you have to implement an interface for java to thread?

    You don't, as you said previously you can extend the Thread object and implement a public void run method. If you want a more organized and flexible (yes, flexible) approach you definitely want to use Runnable for an obvious reason: Code reusability.

    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.

    Whats the importances of the runnable interface that makes java threading work?

    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).

    Does Java's interface extend from something?

    This question is worth my +1 to you. 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.

    I hope it helped. Cheers

    0 讨论(0)
提交回复
热议问题