java多线程简单使用

3. 实现 Callable 接口(了解即可)

Callable 接口与 Runnable 接口类似,都可以用于定义多线程任务,但 Callable 接口的 call() 方法可以有返回值,并且可以抛出异常。下面将详细介绍如何使用 Callable 接口实现 Java 多线程。

a. Callable 接口简介

Callable 接口是 Java 并发包(java.util.concurrent)中的一个泛型接口,其定义如下:

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

其中,V 是返回值的类型,call() 方法是需要实现的任务逻辑,该方法可以抛出异常。

b. 使用步骤

要使用 Callable 接口实现多线程,通常需要以下几个步骤:

  1. 定义一个实现 Callable 接口的类:重写 call() 方法,该方法包含具体的任务逻辑,并返回一个结果。

  2. 创建 Callable 任务实例:实例化实现了 Callable 接口的类。

  3. 创建 ExecutorService 线程池:使用 Executors 工具类创建一个线程池。

    ExecutorService executorService = Executors.newFixedThreadPool(2),这里表示线程池的大小为2,意味着线程池可以同时并发执行 2 个任务,如果任务数大于线程池大小,假如有5个任务,那么线程池会先让 2 个任务开始执行,剩下的 3 个任务会在任务队列中等待。当正在执行的任务完成后,线程池会从任务队列中取出新的任务继续执行,直到所有任务都执行完毕。

  4. 提交 Callable 任务:将 Callable 任务提交给线程池,线程池会返回一个 Future 对象。

Future future1 = executorService.submit(task1)

Future 是一个泛型接口,用于表示异步计算的结果。Future<Integer> 表示这个异步计算的结果是一个
Integer 类型的值。通过 Future 对象,你可以在需要的时候获取任务的执行结果,例如:

java Integer result = future1.get();

get() 方法是一个阻塞方法,如果任务还未完成,调用 get() 方法的线程会被阻塞,直到任务完成并返回结果。

这其实是因为重写的call()方法有返回值且为Integer。

  1. 获取任务结果:通过 Future 对象的 get() 方法获取任务的返回结果。其实就是获得call()方法的返回值。

  2. 关闭线程池:任务执行完毕后,关闭线程池。

c. 示例代码
import java.util.concurrent.*;

// 1. 定义一个实现 Callable 接口的类
class MyCallable implements Callable<Integer> {
    private int number;

    public MyCallable(int number) {
        this.number = number;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= number; i++) {
            sum += i;
        }
        return sum;
    }
}

public class CallableExample {
    public static void main(String[] args) {
        // 2. 创建 Callable 任务实例
        MyCallable task1 = new MyCallable(10);
        MyCallable task2 = new MyCallable(20);

        // 3. 创建 ExecutorService 线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        try {
            // 4. 提交 Callable 任务
            Future<Integer> future1 = executorService.submit(task1);
            Future<Integer> future2 = executorService.submit(task2);

            // 5. 获取任务结果
            System.out.println("Task 1 result: " + future1.get());
            System.out.println("Task 2 result: " + future2.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 6. 关闭线程池
            executorService.shutdown();
        }
    }
}
d. 代码解释
  • MyCallable:实现了 Callable<Integer> 接口,call() 方法计算从 1 到 number 的整数之和,并返回结果。
  • ExecutorService 线程池:使用 Executors.newFixedThreadPool(2) 创建一个固定大小为 2 的线程池。
  • Future 对象executorService.submit(task) 方法将 Callable 任务提交给线程池,并返回一个 Future 对象,用于表示异步计算的结果。
  • Future.get() 方法:该方法用于获取任务的返回结果,如果任务尚未完成,该方法会阻塞当前线程,直到任务完成。
  • executorService.shutdown():关闭线程池,不再接受新的任务,但会等待已提交的任务执行完毕。
e. 注意事项
  • 异常处理call() 方法可以抛出异常,在获取任务结果时,需要处理 InterruptedExceptionExecutionException 异常。
  • 阻塞问题Future.get() 方法是一个阻塞方法,如果任务执行时间较长,会导致当前线程阻塞,直到任务完成。可以使用 Future.isDone() 方法检查任务是否完成,避免阻塞。
  • 线程池管理:使用完线程池后,需要调用 shutdown() 方法关闭线程池,避免资源泄漏。
  • 跟实现Runnable接口不同的是:1.重写的是call方法。2.不再直接运行run方法,而是将call方法内的内容当做任务提交。3.提交后会返回一个Future泛型,其中的类型就是call方法返回的类型。4.可以使用Future类的get方法拿到返回值。4.最后记得关闭服务executorService.shutdown()。

Callable 接口与 Runnable 接口类似,但它可以返回执行结果,并且可以抛出异常。通常结合 FutureTask 类和 ExecutorService 来使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值