LarryDpk
发布于 2023-03-09 / 74 阅读
0

Difference Between Callable and Runnable in Java

Introduction

Both Runnable and Callable are interface for multiple-thread in Java. Let’s compare them with code.

The main differences:

Runnable Interface Callable Interface
Package java.lang.Runnable since JDK 1.0 java.util.concurrent.Callable Since JDK 1.5
Method public abstract void run(); V call() throws Exception;
Exception Can’t Throw an exception; Can throw an exception;
Return Value Can’t return any result; Can returun the result you want;

The definition code

Runnable:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

Callable:

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

How to use

Runnable

Implement the interface with overriding the run() method:

class PkslowRunnable implements Runnable {
    private final String name;

    PkslowRunnable(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + " is running");
        try {
            Thread.sleep(1000);
            System.out.println(name + " is completed");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

We can use ExecutorService to submit the Runnable task:

private static void runnable() {
  ExecutorService executorService = Executors.newFixedThreadPool(4);

  executorService.submit(new PkslowRunnable("pkslow.r1"));
  executorService.submit(new PkslowRunnable("pkslow.r2"));
  executorService.submit(new PkslowRunnable("pkslow.r3"));
  executorService.submit(new PkslowRunnable("pkslow.r4"));
  executorService.submit(new PkslowRunnable("pkslow.r5"));
  executorService.submit(new PkslowRunnable("pkslow.r6"));
  executorService.submit(new PkslowRunnable("pkslow.r7"));
  executorService.submit(new PkslowRunnable("pkslow.r8"));
  executorService.submit(new PkslowRunnable("pkslow.r9"));
  executorService.submit(new PkslowRunnable("pkslow.r10"));

  awaitTerminationAfterShutdown(executorService);
}

Output:

pkslow.r4 is running
pkslow.r2 is running
pkslow.r3 is running
pkslow.r1 is running
pkslow.r2 is completed
pkslow.r4 is completed
pkslow.r1 is completed
pkslow.r3 is completed
pkslow.r5 is running
pkslow.r6 is running
pkslow.r7 is running
pkslow.r8 is running
pkslow.r5 is completed
pkslow.r7 is completed
pkslow.r6 is completed
pkslow.r8 is completed
pkslow.r10 is running
pkslow.r9 is running
pkslow.r10 is completed
pkslow.r9 is completed

Callable

Implement the Callable interface with overriding the call() method:

class PkslowCallable implements Callable<Integer> {
    private final String name;

    PkslowCallable(String name) {
        this.name = name;
    }


    @Override
    public Integer call() throws Exception {
        System.out.println(name + " is running");
        try {
            Thread.sleep(1000);
            System.out.println(name + " is completed");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return (new Random().nextInt()) % 100;
    }
}

We will return a random int as a result.

Similarly, we can use ExecutorService to submit the Callable task:

private static void callable() {
  ExecutorService executorService = Executors.newFixedThreadPool(4);
  List<Future<Integer>> futures = new ArrayList<>();
  futures.add(executorService.submit(new PkslowCallable("pkslow.c1")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c2")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c3")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c4")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c5")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c6")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c7")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c8")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c9")));
  futures.add(executorService.submit(new PkslowCallable("pkslow.c10")));

  futures.forEach(ft -> {
    try {
      System.out.println("Result from Future: " + ft.get());
    } catch (InterruptedException | ExecutionException e) {
      throw new RuntimeException(e);
    }
  });

  awaitTerminationAfterShutdown(executorService);
}

With the Future.get(), we can fetch the result.

Output:

pkslow.c1 is running
pkslow.c3 is running
pkslow.c2 is running
pkslow.c4 is running
pkslow.c2 is completed
pkslow.c1 is completed
pkslow.c3 is completed
pkslow.c4 is completed
pkslow.c5 is running
pkslow.c7 is running
pkslow.c6 is running
pkslow.c8 is running
Result from Future: 62
Result from Future: 3
Result from Future: -1
Result from Future: 38
pkslow.c7 is completed
pkslow.c6 is completed
pkslow.c8 is completed
pkslow.c5 is completed
pkslow.c10 is running
pkslow.c9 is running
Result from Future: 19
Result from Future: -42
Result from Future: 73
Result from Future: 84
pkslow.c10 is completed
pkslow.c9 is completed
Result from Future: -32
Result from Future: -48

Code

Code in GitHub: https://github.com/LarryDpk/pkslow-samples