stackoverflow
stackoverflow

Reputation: 19434

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. But why do you have to implement an interface for java to thread? Whats the importances of the runnable interface that makes java threading work? Does Java's interface extend from something?

Upvotes: 5

Views: 8127

Answers (5)

Basil Bourque
Basil Bourque

Reputation: 338181

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.

Upvotes: 1

seeker4098
seeker4098

Reputation: 11

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.

Upvotes: 1

Mark Peters
Mark Peters

Reputation: 81054

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.

Upvotes: 11

Bruno Vieira
Bruno Vieira

Reputation: 3904

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

Upvotes: 2

Juvanis
Juvanis

Reputation: 25950

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.

Upvotes: 2

Related Questions