ExecutorService中submit()和execute()的区别

在使用java.util.concurrent下关于线程池一些类的时候,相信很多人和我一样,总是分不清submit()和execute()的区别,今天从源码方面分析总结一下。

  通常,我们通过Executors这个工具类提供多种方法来创建适合不同场景的线程池,这里就不一一介绍了。

  execute()方法源码如下:

public interface Executor {
    void execute(Runnable command);
}

       execute()方法的入参为一个Runnable,返回值为void,这时候我们已经知道了execute()方法的来源以及其定义。

  接下来,我们来看看,submit()是从哪来的呢?

  通过猜测,应该是ExecutorService接口中的,果然,打开源码,看到了submit()方法:

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

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

  Future<?> submit(Runnable task);
  ...
}

可以看出,在ExecutorService接口中,一共有以上三个sumbit()方法,入参可以为Callable<T>,也可以为Runnable,而且方法有返回值Future<T>;

总结,从上面的源码以及讲解可以总结execute()和submit()方法的区别:

  1. 接收的参数不一样;

  2. submit()有返回值,而execute()没有;

    例如,有个validation的task,希望该task执行完后告诉我它的执行结果,是成功还是失败,然后继续下面的操作。

  3. submit()可以进行Exception处理;

    例如,如果task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过对Future.get()进行抛出异常的捕获,然后对其进行处理。

  execute()方法实际应用实例,在对list数据进行处理,比如需要调用RestFul或webService服务对list其他字段补齐的时候,就用到execute()方法,代码如下

    /**
	 * 对list字段补齐
	 * @param list
	 * @return
	 */
	public List<VO> findListVO(List<VO> list) {
		List<VO> result = Lists.newArrayList();
		final int taskSize = 2;
		CountDownLatch cdl = new CountDownLatch(taskSize);
		//task-1
		executor.execute(()->deal1(list,cdl));
		//task-2
		executor.execute(()->deal2(list,cdl));
		return result;
	}
	
	/**
	 * 处理方法1
	 * @param list
	 * @param cdl
	 */
	private void deal1(List<? extends VO> list,CountDownLatch cdl) {
		try{
			if(list.size()!=0) {
				list.forEach(item->{});
			}
		} finally {
			cdl.countDown();
		}
	}
	
	/**
	 * 处理方法2
	 * @param list
	 * @param cdl
	 */
	private void deal2(List<? extends VO> list,CountDownLatch cdl) {
		try{
			if(list.size()!=0) {
				list.forEach(item->{});
			}
		} finally {
			cdl.countDown();
		}
	}

submit()方法在实际应用中的实例,比如一个RestFul接口,只支持一个参数查询,上游系统无法改变传参,这时,为了节省效率,支持多参数查询,我们不得不循环去调用接口,这会导致我们的性能非常慢,为了节省效率,我们不得不把查询放到异步里面去做。代码如下:

   /**
	 * submit()方法
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public Map<String,Map<String,String>> findMap(Map<String,String> map) throws Exception {
		Set<String> set = map.keySet();
		Map<String,Map<String,String>> resultMap = Maps.newHashMap();
		if(set.size()==1) {
			Map<String,String> mapResult = queryMap(set.stream().findFirst().get());
			resultMap.put(set.stream().findFirst().get(),mapResult);
		} else {
			try {
				CountDownLatch cdl = new CountDownLatch(set.size());
				set.forEach(item->{
					es.submit(()-> {
						try{
							Map<String,String> maps = queryMap(item);
							resultMap.put(item,maps);
						} finally {
							cdl.countDown();
						}	
					});	
				});
		} catch(Exception e) {
			throw new Exception();
		}
	  }
		return resultMap;
	}

   /**
	 * 调用接口的方法
	 * @param contract
	 * @return
	 */
	public static Map<String,String> queryMap(String contract) {
		Map<String,String> map = Maps.newHashMap();
		return map;
	}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值