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

Callable VS Runnable对比

简介

这两个都是接口,在Java多线程中用得很多。主要区别有:

Runnable Interface Callable Interface
类包 java.lang.Runnable,JDK 1.0就有 java.util.concurrent.Callable, JDK 1.5引入
方法 public abstract void run(); V call() throws Exception;
异常 不可以抛异常; 可以抛异常;
返回值 不可以返回值; 可以返回任意对象;支持泛型。

代码定义

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

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;
}
Java

如何使用

Runnable

需要实现run()方法:

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);
        }
    }
}
Java

我们可以使用 ExecutorService 来提交Runnable任务:

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);
}
Java

输出:

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
Bash

Callable

需要实现call()方法:

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;
    }
}
Java

这里我们直接返回一个随机结果。

同样,我们也是可以使用 ExecutorService 来提交 Callable 任务:

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);
}
Java

通过调用 Future.get(),我们可以拿到对应的结果。

输出:

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
Bash

代码

代码请查看GitHub: https://github.com/LarryDpk/pkslow-samples