Executors+Callable 、Runnable创建线程池运用实例

局方要求项目满足大批量工单提交,所以这几天学习了下线程池,这里分享一下,其中还有个遇到的问题。如果代码写的有问题,欢迎大神指点。

首先这里运用最简单的线程池创建方法Executors.newFixedThreadPool(5),这里是创建5个线程,不太明白的同学可以去搜索一下,其实底层还是运用 new ThreadPoolExecutor()。这里的队列没有指定长度默认为2147483647(integer最大值,够用了)

这是java的源码:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

 

言归正传,线程的创建使用了两个方法,一个是有回参的还有个是无回参。

先说有回参的,这个是实现Callable接口的,这个接口是有返回值的,我们可以利用有参构造传参。

public class CallableTest implements Callable<DaoTest>{
    private String id;
    public  CallableTest(String id) {
        this.id=id;        
    }
    @Override
    public DaoTest call() throws Exception {
        System.out.println("线程 "+Thread.currentThread().getName()+"开始执行"+new Date());
        DaoTest test=new DaoTest();//这个是模拟业务,从数据库查询数据。
        DaoTest daotest = test.byid(id);
        System.out.println("线程 "+Thread.currentThread().getName()+"结束执行"+new Date());
        return daotest;
    }

}

这个是测试类

public class ControllTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {        
        ExecutorService exec = Executors.newFixedThreadPool(3);
        List<Future<DaoTest>> list = new ArrayList<Future<DaoTest>>();        
        for (int i = 0; i < 5; i++) {
            CallableTest callable = new CallableTest(i+"");//创建Callable接口实例            
             Future<DaoTest> csf = exec.submit(callable);
            list.add(csf);            
        }
        for (Future<DaoTest>fs:list) {
            try {
                System.out.println(fs.get().toString());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        exec.shutdown();

运行的结果

线程 pool-1-thread-3开始执行Wed Oct 17 17:43:32 CST 2018
线程 pool-1-thread-2开始执行Wed Oct 17 17:43:32 CST 2018
线程 pool-1-thread-1开始执行Wed Oct 17 17:43:32 CST 2018
线程 pool-1-thread-3结束执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-3开始执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-2结束执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-2开始执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:43:36 CST 2018
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
线程 pool-1-thread-3结束执行Wed Oct 17 17:43:40 CST 2018
线程 pool-1-thread-2结束执行Wed Oct 17 17:43:40 CST 2018
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]

 

其实我刚开始是直接在for循环打印日志,之前是这样写的

public class ControllTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {        
        ExecutorService exec = Executors.newFixedThreadPool(3);
        List<Future<DaoTest>> list = new ArrayList<Future<DaoTest>>();        
        for (int i = 0; i < 5; i++) {
            CallableTest callable = new CallableTest(i+"");//创建Callable接口实例            
             Future<DaoTest> csf = exec.submit(callable);
            list.add(csf);            
            System.out.println(csf.get().toString());    
//  get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回执行结果;
        }
        for (Future<DaoTest>fs:list) {
            try {
                System.out.println(fs.get().toString());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        exec.shutdown();

下面是执行的结果,可以看到虽然使用了线程池,但是变成单线程执行,其他线程阻塞了,因为csf.get()这个方法会产生线程阻塞,我这里直接获取结果,从而产生其他线程阻塞,这个在项目运用中需要注意

线程 pool-1-thread-1开始执行Wed Oct 17 17:45:44 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:45:48 CST 2018
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
线程 pool-1-thread-2开始执行Wed Oct 17 17:45:48 CST 2018
线程 pool-1-thread-2结束执行Wed Oct 17 17:45:52 CST 2018
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
线程 pool-1-thread-3开始执行Wed Oct 17 17:45:52 CST 2018
线程 pool-1-thread-3结束执行Wed Oct 17 17:45:56 CST 2018
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
线程 pool-1-thread-1开始执行Wed Oct 17 17:45:56 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:46:00 CST 2018
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
线程 pool-1-thread-1开始执行Wed Oct 17 17:46:00 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:46:04 CST 2018
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]

接下来我们看下Runnable接口,首先实现Runnable

public class RunnableService implements Runnable{
    String id;
    public  RunnableService(String id) {
        this.id=id;    
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    @Override
    public void run() {
        
        try {
            System.out.println("线程 "+Thread.currentThread().getName()+"开始执行"+new Date());
            DaoTest test=new DaoTest();
            DaoTest daotest = test.byid(id);
            System.out.println(daotest.toString());
            System.out.println("线程 "+Thread.currentThread().getName()+"结束执行"+new Date());
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

接着测试类

public class ControllTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {        

        ExecutorService poll = Executors.newFixedThreadPool(3);    
        for (int i = 0; i <5; i++) {  
              RunnableService run=new RunnableService(i+"");
              poll.execute(run);    
        }
        poll.shutdown();
        
    }
}

执行结果

线程 pool-1-thread-2开始执行Wed Oct 17 18:02:46 CST 2018
线程 pool-1-thread-1开始执行Wed Oct 17 18:02:46 CST 2018
线程 pool-1-thread-3开始执行Wed Oct 17 18:02:46 CST 2018
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
线程 pool-1-thread-3结束执行Wed Oct 17 18:02:50 CST 2018
线程 pool-1-thread-3开始执行Wed Oct 17 18:02:50 CST 2018
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
线程 pool-1-thread-1结束执行Wed Oct 17 18:02:50 CST 2018
线程 pool-1-thread-1开始执行Wed Oct 17 18:02:50 CST 2018
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
线程 pool-1-thread-2结束执行Wed Oct 17 18:02:50 CST 2018
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]
线程 pool-1-thread-1结束执行Wed Oct 17 18:02:54 CST 2018
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
线程 pool-1-thread-3结束执行Wed Oct 17 18:02:54 CST 2018

如果有问题欢迎联系我。

这里还有个问题,当我们需要返回参数的时候,通常存在容器中,如何返回给前端正确的返回值呢?留个问题之后在更新。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值