📜  Java和 Android 多线程编程中的 Runnable、Callable、Future、Executor(1)

📅  最后修改于: 2023-12-03 15:32:02.822000             🧑  作者: Mango

Java和Android多线程编程中的Runnable、Callable、Future、Executor

概述

在现代编程中,多线程编程是非常常见的。Java和Android提供了许多类和接口来支持多线程编程,其中最常用的有Runnable、Callable、Future和Executor。

Runnable和Callable是两个接口,它们允许我们在不同的线程中执行任务。Runnable只能返回void,而Callable可以返回一个值。Future是一个接口,允许我们通过一个obj来获取线程的结果。Executor是一个接口,它允许我们通过一个线程池来管理线程。

在本文中,我们将详细讲解这些接口,包括它们的工作原理、使用方法和示例代码。

Runnable

Runnable是Java中最常见的多线程接口。它定义了一个用于执行任务的单线程。

public interface Runnable {
    public abstract void run();
}

这个接口只有一个方法run(),这个方法里面包含了我们要执行的代码。需要注意的是run()方法不能返回任何值。

以下是一个简单的Runnable代码片段:

Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello World");
    }
};

Thread thread = new Thread(task);
thread.start();

这里我们定义了一个匿名Runnable对象,然后使用Thread类来创建一个新的线程。在start()方法被调用后,线程将异步执行Runnable对象的run()方法。

Callable

Callable是一个更加强大的多线程接口,它允许我们执行一个任务,并返回一个结果。与Runnable不同的是,Callable需要使用ExecutorService来执行。

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

Callable接口只有一个方法call(),这个方法会在ExecutorService中被执行。它允许我们在执行任务的过程中抛出异常,并返回一个结果。

以下是一个简单的Callable代码片段:

Callable<Integer> task = new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 42;
    }
};

ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> result = executor.submit(task);

System.out.println("Result: " + result.get());

executor.shutdown();

这里我们定义了一个Callable对象,它会在执行期间休眠了1秒钟,最后返回值42。我们使用了ExecutorService来提交执行Callable任务,然后使用Future来获取返回值。最后我们需要调用executor.shutdown()方法来停止ExecutorService。

Future

Future是一个允许我们异步获取线程结果的接口。它包含了4个方法,最常用的是get()方法。我们可以使用这个方法来等待线程完成,并获取线程的结果。如果线程还没有完成,get()方法会阻塞当前线程。

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

以下是一个简单的Future代码片段:

ExecutorService executor = Executors.newFixedThreadPool(1);
Future<Integer> result = executor.submit(() -> 42);

while (!result.isDone()) {
    Thread.sleep(100);
}

System.out.println("Result: " + result.get());

这里我们使用ExecutorService来提交一个Callable任务。在提交后,我们使用while循环来等待任务完成。当isDone()方法返回true时,我们就可以使用result.get()方法来获取结果。

Executor

Executor是一个用于管理线程的接口。它允许我们通过线程池来管理线程,可以使得我们的系统更加高效地运行。除了管理线程之外,Executor还可以提供错误处理、队列管理和任务取消等功能。

public interface Executor {
    void execute(Runnable command);
}

Executor只有一个方法execute(),这个方法用于执行任务。

以下是一个简单的Executor代码片段:

ExecutorService executor = Executors.newFixedThreadPool(2);

for (int i = 0; i < 10; i++) {
    executor.execute(() -> {
        System.out.println("Hello World");
    });
}

executor.shutdown();

在这里,我们定义了一个具有2个线程的Executor。然后我们循环执行了10个任务,并使用execute()方法来提交任务。最后我们需要调用executor.shutdown()方法来停止ExecutorService。

总结

Java和Android提供了许多类和接口来支持多线程编程,其中最常用的有Runnable、Callable、Future和Executor。Runnable和Callable是两个接口,它们允许我们在不同的线程中执行任务。Future是一个接口,允许我们通过一个obj来获取线程的结果。Executor是一个接口,它允许我们通过一个线程池来管理线程。熟练使用这些接口可以使我们的代码更加高效和可靠。