LarryDpk
发布于 2023-03-09 / 90 阅读
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();
}

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

如何使用

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

我们可以使用 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);
}

输出:

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

需要实现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;
    }
}

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

同样,我们也是可以使用 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);
}

通过调用 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

代码

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