JAVA异步任务

2,480 阅读2分钟

1.基本接口

  • Runnable位于java.lang包下
  • Callable位于java.util.concurrent包下

2.运行机制

2.1 Runable

JDK8中Runnable接口源码如下:

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

从源码到Runnable接口是一个函数式接口只有一个抽象方法run(),且Runnable是没有返回值的。通过实现该接口创建任务类,将任务逻辑写在run()方法中,并将任务类对象传给Thread类的构造方法,运行它的start()方方法启动线程执行异步任务对象,但任务完成后无法返回任何结果。

其实Thread类也继承了Runnable接口。其部分源码如下:

public class Thread implements Runnable {
 /* What will be run. */
 private Runnable target;

 @Override
 public void run() {
        if (target != null) {
            target.run();
        }    
}
 public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
private native void start0();......}

Thread通过执行start()方法中的strart0()创建线程并在start0()中调用run()方法执行。

2.2  Callable接口

Callable接口JDK8源码如下:

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

Callable接口同样是一个函数式接口,只有一个抽象方法call(),异步任务逻辑同样在该方法中实现。与run()方法不同的是call()不近有返回值还可以抛出异常。

Callable无法直接通过Thread类来执行。Callable一般结合ExecutorService来提交执行,并结和Future来获取结果。

ExecutorService中提交任务的方法:

public interface ExecutorService extends Executor{
    
    <T> Future<T> submit(Callable<T> task);

    
    <T> Future<T> submit(Runnable task, T result);


    Future<?> submit(Runnable task);

   }

这三个submit方法都是提交一个任务,返回值都是Future对象。可以通过Future对象来查询任务的状态,获取任务的最终结果,取消任务。