线程池深度剖析

java线程池使用Executors.newFixedThreadPool创建,创建后,返回ExecutorService对象,该对象除了调用execute()执行线程以外

还有submit()方法,那这两者之间有何区别?接下来我们通过查看submit的底层实现来深挖两者区别。

ExecutorService的实现类是AbstractExecutorService,submit()有三种参数类型,分别为:

public Future<?> submit(Runnable var1)
public <T> Future<T> submit(Runnable var1, T var2)
public <T> Future<T> submit(Callable<T> var1) 

发现上面传参主要是两种,一种是Runnable,一种是Callable,这两个接口有什么区别呢,看下方法的具体实现:

public <T> Future<T> submit(Runnable var1, T var2) {
        if (var1 == null) {
            throw new NullPointerException();
        } else {
            RunnableFuture var3 = this.newTaskFor(var1, var2);
            this.execute(var3);
            return var3;
        }
    }

public <T> Future<T> submit(Callable<T> var1) {
    if (var1 == null) {
        throw new NullPointerException();
    } else {
        RunnableFuture var2 = this.newTaskFor(var1);
        this.execute(var2);
        return var2;
    }
}

两者都调用了newTaskFor()

protected <T> RunnableFuture<T> newTaskFor(Runnable var1, T var2) {
        return new FutureTask(var1, var2);
}

protected <T> RunnableFuture<T> newTaskFor(Callable<T> var1) {
        return new FutureTask(var1);
}

方法类生成了FutureTask对象,继续看FutureTask类的两个构造方法:

public FutureTask(Callable<V> var1) {
        if (var1 == null) {
            throw new NullPointerException();
        } else {
            this.callable = var1;
            this.state = 0;
        }
}

public FutureTask(Runnable var1, V var2) {
        this.callable = Executors.callable(var1, var2);
        this.state = 0;
}

其中传递Callabla参数的方法,直接指定了callable的值,而传递Runnable参数的调用了Executors.callable方法,我们看下这个方法:

public static <T> Callable<T> callable(Runnable var0, T var1) {
        if (var0 == null) {
            throw new NullPointerException();
        } else {
            return new Executors.RunnableAdapter(var0, var1);
        }
}
static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;

        RunnableAdapter(Runnable var1, T var2) {
            this.task = var1;
            this.result = var2;
        }

        public T call() {
            this.task.run();
            return this.result;
        }
}

发现最后底层通过RunnableAdapter,将Runnable转化成了Callable,并且返回了传递的result对象。所以本质上submit()提交的Callable和Runnable如出一辙。都是生成一个FutureTask对象,并且赋值对象中的callable和state属性

我们继续返回到上面的submit()方法,newTaskFor方法调用以后,返回了RunnableFuture接口类型,该接口只有一个run()方法,我们到该接口实现类FutureTask中看下run()方法的实现:

public void run() {
        if (this.state == 0 && UNSAFE.compareAndSwapObject(this, runnerOffset, (Object)null, Thread.currentThread())) {
            boolean var9 = false;

            try {
                var9 = true;
                Callable var1 = this.callable;
                if (var1 != null) {
                    if (this.state == 0) {
                        Object var2;
                        boolean var3;
                        try {
                            var2 = var1.call();
                            var3 = true;
                        } catch (Throwable var10) {
                            var2 = null;
                            var3 = false;
                            this.setException(var10);
                        }

                        if (var3) {
                            this.set(var2);
                            var9 = false;
                        } else {
                            var9 = false;
                        }
                    } else {
                        var9 = false;
                    }
                } else {
                    var9 = false;
                }
            } finally {
                if (var9) {
                    this.runner = null;
                    int var6 = this.state;
                    if (var6 >= 5) {
                        this.handlePossibleCancellationInterrupt(var6);
                    }

                }
            }

            this.runner = null;
            int var12 = this.state;
            if (var12 >= 5) {
                this.handlePossibleCancellationInterrupt(var12);
            }

        }
 }

本质上是调用了callable的call方法,结合之前的分析,就是如果submit传递的是callable则调用其call()方法,如果传递的是runnable(底层通过RunableAdapter实现了callable),则调用run()方法。

在submit()方法中,生成FutureTask后的下一步就是this.execute()执行,即会执行FutureTask的run方法。

到这里我们基本已经清楚submit执行原理了,那为什么还要返回一个FutureTask类呢,既然已经执行了callable的call或者runnable的run,返回这个类不是多此一举?

因为FutureTask中还有个get()方法:

public V get() throws InterruptedException, ExecutionException {
        int var1 = this.state;
        if (var1 <= 1) {
            var1 = this.awaitDone(false, 0L);
        }

        return this.report(var1);
}

通过这个方法,我们能获取到线程执行完后,我们先前已经传递进去的泛型,可以用来判断线程是否执行完毕,这一点是execute()方法所不具备的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值