Callable接口中的call方法及返回对象Future 和CountDownLatch计数器的使用

jdk1.5中的实现Callable接口中实现call方法创建线程与之前Thread类中或Runnable接口中的重写/实现run方法的不同

首选call方法最大不同就是增加了抛出异常及其返回值的功能。
Callable接口与Future, 多线程并发情况下利用Future对象接收返回值,上代码。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestCallable {
	public static void main(String[] args) throws Exception{
		ExecutorService es = Executors.newCachedThreadPool();
		
		Callable<Integer> task1 = new Callable<Integer>(){
			public Integer call() throws Exception{
				System.out.println("task1 start working");
				int result = 0 ; 
				for(int i = 1 ; i < 100 ; i+=2){
					result += i;
					Thread.sleep(100);
				}
				System.out.println("task1 end working");
				return result;
			}
		};
		Callable<Integer> task2 = new Callable<Integer>(){
			public Integer call() throws Exception{
				System.out.println("task2 start working");
				int result = 0 ; 
				for(int i = 2 ; i <= 100 ; i+=2){
					result += i;
					Thread.sleep(100);
				}
				System.out.println("task2 end working");
				return result;
			}
		};		
		Future<Integer> f1 = es.submit(task1);
		Future<Integer> f2 = es.submit(task2);
		System.out.println("main do sth");
		
		int result = f1.get()+f2.get();
		System.out.println(result);
		
		es.shutdown();
	}
}
   @Override
       public Map selectAllCountByFuture() throws Exception {
           Map map = new HashMap();
   
   //        1.开启多个线程
   //        查询 性别
           Future<Boolean> future1 = ThreadPollUtil.executor.submit(new Callable<Boolean>() {
               @Override
               public Boolean call() throws Exception {
                   List<Map> maps = selectBySexCount();
                   map.put("sex",maps);
                   return true;
               }
           });
   //        查询 地区分布
           Future<Boolean> future2 = ThreadPollUtil.executor.submit(new Callable<Boolean>() {
               @Override
               public Boolean call() throws Exception {
                   List<Map> province = selectByProvince();
                   map.put("province",province);
                   return true;
               }
           });
   
   //        查询 注册量
           Future<Boolean> future3 = ThreadPollUtil.executor.submit(new Callable<Boolean>() {
   
               @Override
               public Boolean call() throws Exception {
                   Map map1 = selectByDayCount();
                   map.put("count",map1);
                   return true;
               }
           });
   
   //        代表全部线程执行完毕
           if (future1.get() && future2.get() && future3.get()){
               return map;
           }
           return null;
       }

ThreadPollUtil 工具类

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPollUtil {

    /**
     * IO密集型任务  (常出现于线程中:数据库数据交互、文件上传下载、网络数据传输等等 能够体现多核处理器的优势)
     * CPU密集型任务 (常出现于线程中:复杂算法 能体现CPU版本的优势)
     */
    private static int corePoolSize = Runtime.getRuntime().availableProcessors();

    /**
     * public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,
     *                           TimeUnit unit,BlockingQueue<Runnable> workQueue)
     * corePoolSize用于指定核心线程数量
     * maximumPoolSize指定最大线程数
     * keepAliveTime和TimeUnit指定线程空闲后的最大存活时间
     * workQueue则是线程池的缓冲队列,还未执行的线程会在队列中等待
     * 监控队列长度,确保队列有界
     * 不当的线程池大小会使得处理速度变慢,稳定性下降,并且导致内存泄露。如果配置的线程过少,则队列会持续变大,消耗过多内存。
     * 而过多的线程又会 由于频繁的上下文切换导致整个系统的速度变缓——殊途而同归。队列的长度至关重要,它必须得是有界的,这样如果线程池不堪重负了它可以暂时拒绝掉新的请求。
     * ExecutorService 默认的实现是一个无界的 LinkedBlockingQueue。
     */
    public static ThreadPoolExecutor executor  = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10l, TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(1000));

}

还有countdownlatch的使用

 @Override
       public Map selectAllCountByThread() throws InterruptedException {
           Map map = new HashMap();
   //        1.创建任务计数器  参数为设置任务数量
           CountDownLatch countDownLatch = new CountDownLatch(3);
   
   //        2.开启三个线程  分别执行三个查询
   //        查询 性别信息
           ThreadPollUtil.executor.submit(new Runnable() {
               @Override
               public void run() {
                   List<Map> maps = selectBySexCount();
   //                得到查询结果
                   map.put("sex",maps);
   //                计数器减一
                   countDownLatch.countDown();
               }
           });
   //        查询 地区分布
           ThreadPollUtil.executor.submit(new Runnable() {
               @Override
               public void run() {
                   List<Map> maps = selectByProvince();
                   //                得到查询结果
                   map.put("province",maps);
                   //                计数器减一
                   countDownLatch.countDown();
   
               }
           });
   
   //        查询 注册量
           ThreadPollUtil.executor.submit(new Runnable() {
               @Override
               public void run() {
                   Map map1 = selectByDayCount();
                   map.put("count",map1);
                   countDownLatch.countDown();
               }
           });
   
 //        await() 当计数器为0的时候 主线程向下执行 没有这一步的话,如果一旦主线程向下执行
           // return map map中可能有的开启的线程还没有执行完毕,即返回的不是线程执行后的结果
           countDownLatch.await();
   
           return map;
       }

countDownLatch 和 Future 区别
countDownLatch 更加的简洁 判断所有任务是否执行成功的时候 不需要做复杂的逻辑判断

这辈子坚持与不坚持都不可怕,怕的是独自走在坚持的道路上!!!

创建线程
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值