Java 使用 Callable 接口创建线程
  anLrwkgbyYZS 2023年12月30日 21 0


使用 Callable 接口创建线程相较于实现 Runnable 接口方式的优点:可以有返回值,可以抛出异常。

 1. 概述

Callable 接口的源码如下所示:@FunctionalInterface 表名是一个函数式的接口,可以有返回值 V (泛型),可以抛出异常 throws Exception。call 方法类似  Runnable 接口 中的 run 方法,作为线程的 执行体。

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

2. FutureTask

FutureTask 类实现 RunnableFuture接口。

public class FutureTask<V> implements RunnableFuture<V>

 RunnableFuture接口 实现 Runnable 和 Future。

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

 FutureTask 的 run 方法调用 call 方法 ,等待  call 方法  执行完毕,存储 call 方法的返回值,然后  FutureTask  可以通过 get 方法 获取  call 方法的返回值。接下来看一下 FutureTask 的 源码。

 FutureTask 的 run 方法如下所示:

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call(); // 调用 call 方法
                    ran = true; // 成功调用则会有返回值
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result); // 返回值
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

 set 方法如下所示,使用 CAS(乐观锁的一种形式) 设置返回值到outcome。

protected void set(V v) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = v;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
            finishCompletion();
        }
    }

 get 方法获取 outcome。

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

report 方法如下所示:

private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

3. 代码示例

重写 call 方法:

@Override
    public Integer call() throws Exception {
        int times = 1000;
        for (int i=0; i<times; i++) {
            if(i%100 == 0)
            System.out.println(Thread.currentThread().getName());
        }
        return times;
    }

 使用 FutureTask 类包装 Callable 接口的实现类。

FutureTask<Integer> task = new FutureTask<Integer>(new MyCallableStudy());

启动线程。

new Thread(task, "callable").start();

获取返回值。

task.get();

完整代码如下所示: 

package callable;

import java.util.concurrent.*;

public class MyCallableStudy implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int times = 1000;
        for (int i=0; i<times; i++) {
            if(i%100 == 0)
            System.out.println(Thread.currentThread().getName());
        }
        return times;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> task = new FutureTask<Integer>(new MyCallableStudy());
        new Thread(task, "callable").start();
        System.out.println(task.get());
    }
}

运行截图:

Java 使用 Callable 接口创建线程_ide

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月30日 0

暂无评论

推荐阅读
  anLrwkgbyYZS   2023年12月30日   12   0   0 ideciciMaxideMax
anLrwkgbyYZS