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