首页 > 编程语言 > 详细

java学习:线程池和异步

时间:2016-03-07 01:20:00      阅读:281      评论:0      收藏:0      [点我收藏+]

1.异步和同步

同步执行很容易理解,代码的操作顺序就是程序执行的顺序。但是实际使用中,很多场景常常会受限于同步执行,不能充分利用cpu的资源,例如,要查找一大批数据中的最大数,同步执行时,可能是花费1单位的cpu,在10单位时间后得到结果;而,异步执行时,分派10个线程执行任务,将会花费10单位的cpu,在1单位时间后得到结果。

相对于同步而言,异步本质上是申请线程,占用更多的cpu资源更快地得到结果。在解决问题时合理地选择同步和异步能更好地利用好计算资源。

从数据的角度来看,在同步操作中,数据的变化都保持一定的先后顺序关系,不会出现冲突的情况;而在异步操作中,数据随时可能被其中某个线程更改,这时需要注意数据的一致性,尤其是写操作,要保证事务性,这里可以对数据加锁来实现。另外有时线程之间也需要保证一定的顺序,需要使用线程锁(这里有的可以通过编码技巧或者回调方法解决)。

 

2.线程池

在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因。比如大家所熟悉的数据库连接池正是遵循这一思想而产生的,接下来将介绍的线程池技术同样符合这一思想。

在java中,可以使用java.util.concurrent.ThreadPoolExecutor来创建线程池,

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

创建方法中的几个参数需要注意:

先说最重要的3个参数,corePoolSize,maximumPoolSize,workQueue。corePoolSize设定核心线程数,maximumPoolSize设定最大线程数,workQueue设定等待队列。当有新任务时,首先检查当前的线程数是否小于corePoolSize,如果是,则新建线程处理任务;如果不是,再检查当前workQueue是否已满,如果未满,则把新的任务加入workQueue,core线程完成时会从workQueue中取得任务继续执行;如果workQueue已满,再检查当前线程数是否小于maximumPoolSize,如果是,则创建线程处理任务,如果不是,则抛出拒绝服务的异常(默认是抛出异常,具体如何处理是最后一个参数RejectExecutionHandler来决定的)。

其他的参数分别是,keepAliveTime、unit控制空闲线程的存活时间;threadFactory,创建新的线程时使用的创建者;handler,拒绝服务时的处理方式;(后两个参数都有默认的选择)

 

从线程池的工作方式可以看到,core,max,queue决定了线程池的表现,下面讲述这三个参数的参考设定。

一般来说,需要处理qps平均为n,最大为m,每个请求的处理时间为t(秒)时,core=nt+,max=mt+,queue视需要而定(当这些请求需要尽快响应,cpu资源常有空闲时,queue=0)

对于cpu密集型任务,如大量数据的计算,匹配,排序等,这时cpu的处理能力成为瓶颈,core和max要注意不要设定得太大,要衡量好cpu的处理能力。

对于io密集型任务,如操作数据库,http请求等,core和max可以考虑设定得更大,因为线程通常处于等待之中,不会耗费多少cpu。

 

===========后面补充异步的使用样例===========

java学习:线程池和异步

原文:http://www.cnblogs.com/just84/p/5249033.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!