java多线程(12) Runable与Callable

Runable与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;
}
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface Runnable is used
     * to create a thread, starting the thread causes the object's
     * run method to be called in that separately executing
     * thread.
     * 

* The general contract of the method run is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }

通过注释我们可以看出Callable中的call方法有返回值并且会抛出异常。
关于这个返回值怎么获取,以及这个异常怎么catch:
返回值:
首先我们看看这个方法在哪里被调用
在这里插入图片描述
去这个FutureTask看看

    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();
                    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.说明我们往FutureTask中塞了Callable
Callable<V> c = callable;
2.调用了call()方法
V result;
result = c.call();
3.将执行结果set到某处
set(result);

以上的1什么时候执行的呢
我们看看FutureTask的构造器:

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

这里正好可以传入一个callable,那么这个构造器什么时候执行的呢,我们可能是new了一个FutureTask或者FutureTask的子类
java多线程(12) Runable与Callable_第1张图片
排除其他的,最像的可能就是这个AbstractExecutorService了

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
    
        public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

有个submit方法,它是实现了ExecutorService中的 Future submit(Runnable task, T result);
并且有个ThreadPoolExecutor实现类:
java多线程(12) Runable与Callable_第2张图片
这个ThreadPoolExecutor不是抽象类,可以直接new

异常怎么catch:
call()会抛出异常,那么他的调用方run()也会抛出异常或者catch,
结果我们发现在run里面是catch了的:

                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
    protected void setException(Throwable t) {
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = t;
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
            finishCompletion();
        }
    }

在没有异常时,outcome就是执行结果,有异常就是Throwable子类
在get方法中就可以获取返回值了:

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

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

于是,就有了下面这个demo:

public class CallableDemo1 {
    public static void main(String[] args) {
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0
                , TimeUnit.SECONDS, new LinkedBlockingQueue<>(), threadFactory);
        Future<String> future = threadPoolExecutor.submit(new MyCallable());
        try {
            System.out.println(future.get());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Thread.currentThread().interrupt();
        }
        System.out.println("程序结束");
        while (true) {
            if (Thread.currentThread().isInterrupted()) {
                threadPoolExecutor.shutdown();
                break;
            }
        }
    }
}

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("程序正在执行");
        Thread.sleep(5000);
        return "程序执行成功";
    }
}

你可能感兴趣的:(java多线程与并发)