Java JUC并发之Callable接口

七、 Callable

相较于Runnable来说,Callable => :

  • 可以有返回值
  • 可以抛出异常
  • 方法不同, run() => Runnable、 call() => Callable

代码测试

package com.liu.callable;

import java.util.concurrent.*;

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // new Thread( new Runnable() ).start();
        // new Thread( new FutureTask<V>() ).start();
        // new Thread( new FutureTask<V>( Callable) ).start();
        // new Thread().start() 怎么启动Callable 使用适配类 FutureTask


        MyThread thread = new MyThread();
        FutureTask futureTask = new FutureTask(thread); // FutureTask => 适配类
        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start(); // 结果会被缓存,可以提高效率


        String r = (String) futureTask.get(); // 获取返回结果 get()可能会产生阻塞 将它放到最后 或者 使用异步通信

        System.out.println(r);

       /* // 创建执行服务
        ExecutorService service = Executors.newFixedThreadPool(1);

        // 提交执行
        Future<String> res = service.submit(thread);

        // 获得执行结果
        try {
            String r = res.get();
            System.out.println(r);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        // 关闭服务
        service.shutdown();*/

    }
}

class MyThread implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println("call()");
        return "ybb";
    }
}

FutureTask源码中的run() :

    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

public void run() {
       // 如果线程已经被执行过一次(不处于新生状态),则直接返回 
       // 对 FutureTask中 的 volatile 类型的变量 state(当前线程的状态) 进行判断  
        if (state != NEW ||
            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.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);
        }
    }

总结:

  1. Callable可以有返回值,也可以抛出异常;
  2. Callable需要使用适配类FutureTask来启动;
  3. Callable实现的多线程有缓存,结果可能需要等待,会阻塞!
posted @ 2021-07-15 16:56  夕立君  阅读(166)  评论(0编辑  收藏  举报