Those things in Java Runnable and Callable of

image

1 Overview

Since the early Java, Multithreading has been a major aspect of the language. Runnable is used to represent multithreaded core interfaces, Callable is an improved version of the Runnable Java 1.5 is added.

In this article, we will explore the differences and the application of the two interfaces.

2. Implementation Mechanism

Both interfaces are intended to represent the task can be performed by multiple threads. Runnable task can be used to run threads or ExecutorService class, and can only be run with a call to the latter.

3. Return value

Let us understand the way the process returns to the value of these interfaces.

3.1 Runnable

Runnable interface is a function interface, and has a single run () takes no parameters and does not return any value method.

This applies to the case we do not find the thread execution result, for example, the incoming event logging:

public interface Runnable {
    public void run();
}

Let's understand this with an example:

public class EventLoggingTask implements  Runnable{
    private Logger logger = LoggerFactory.getLogger(EventLoggingTask.class);
 
    @Override
    public void run() {
        logger.info("Message");
    }
}

In this example, the thread will only read messages from the queue and recorded in a log file. Task does not return any value; you can use ExecutorService start the task:

public void executeTask() {
    executorService = Executors.newSingleThreadExecutor();
    Future future = executorService.submit(new EventLoggingTask());
    executorService.shutdown();
}

In this case, Future objects do not retain any value.

3.2 Callable

Callable Interface comprising a single, generic call () method call - it returns a generic value V:

public interface Callable<V> {
    V call() throws Exception;
}

We take a look compute factorial of a number:

public class FactorialTask implements Callable<Integer> {
    int number;
 
    // standard constructors
 
    public Integer call() throws InvalidParamaterException {
        int fact = 1;
        // ...
        for(int count = number; count > 1; count--) {
            fact = fact * count;
        }
 
        return fact;
    }
}

Results call () method returns the object Future:

@Test
public void whenTaskSubmitted_ThenFutureResultObtained(){
    FactorialTask task = new FactorialTask(5);
    Future<Integer> future = executorService.submit(task);
  
    assertEquals(120, future.get().intValue());
}

4. The Exception Handling

Let's look at the extent they apply to exception handling.

4.1 Runnable

Since the method signature does not specify "throws" clause, an exception can not be spread further examination.

4.2 Callable

Callable's call () method includes "throws Exception" clause, so we can easily further spread of abnormal checked:

public class FactorialTask implements Callable<Integer> {
    // ...
    public Integer call() throws InvalidParamaterException {
 
        if(number < 0) {
            throw new InvalidParamaterException("Number should be positive");
        }
    // ...
    }
}

If you expect to have a return value, then this case is recommended Callable, exceptions are objects collected in the future, this can make a call to Future.get to be examined () method. This will throw an exception ExecutionException its original packaging:

@Test(expected = ExecutionException.class)
public void whenException_ThenCallableThrowsIt() {
  
    FactorialCallableTask task = new FactorialCallableTask(-5);
    Future<Integer> future = executorService.submit(task);
    Integer result = future.get().intValue();
}

In the above test, throw ExecutionException, because we passed is a valid number. We can call getCause () method on this exception object to get the raw checked exceptions.

If we do not get Future class call () method - then call () method throws an exception report will not be coming back, and the task will be marked as completed:

@Test
public void whenException_ThenCallableDoesntThrowsItIfGetIsNotCalled(){
    FactorialCallableTask task = new FactorialCallableTask(-5);
    Future<Integer> future = executorService.submit(task);
  
    assertEquals(false, future.isDone());
}

Even if we have a negative argument to throw FactorialCallableTask, the above test will be successful.

5 Conclusion

In this article, we discuss the differences between Runnable and Callable interfaces.

image

Micro-channel attention: Java confidant
update Java knowledge every day Oh, look forward to your arrival!

image

Guess you like

Origin blog.csdn.net/feilang00/article/details/86685675