多线程模式——Active Object(主动对象)模式

这些都是根据我最近看的《Java实战指南多线程编程(设计模式篇)》所得整理。

模式名称

Active Object(主动对象)模式

模式解决的问题

有的时候需要线程中的方法与调用分离,即在线程外用方法调用线程内方法,可是线程内的方法不能被直接调用,所以需要这里的主动对象模式处理这个问题。

解决思路

Proxy类负责对外暴露异步方法接口,其中asyncService方法负责创建与该方法相应的MethodRequest参与者实例,并将其提交给Scheduler参与者实例。
MethodRequest类负责将客户端代码对Proxy实例的异步方法的调用封装为一个对象,该对象保留了异步方法的名臣即客户端代码传递的参数等上下文信息,它使得Proxy的异步方法的调用和执行分离成为可能。call根据其所属MethodRequest实例锁包含的上线文信息调用Servant实例的相应方法。
ActivationQueue类缓冲区,用于临时存储有Proxy的异步方法被调用时锁创建的MethodRequest实例。enqueue将MethodRequest实例放入缓冲区,dequeue从缓冲区中取出一个MethodRequest实例。
Scheduler类负责将Proxy的异步方法所创建的MethodRequest实例存入其维护的缓冲区中,并根据一定的调度策略,对其维护的缓冲区的MethodRequest实例进行执行。enqueue接受一个MethodRequest实例,并将其存入缓冲区。dispatch反复地从缓冲区中取出MethodRequest实例进行执行。
Servant类负责Proxy所暴露的异步方法的具体实现。doSomething执行Proxy锁暴露的异步方法对应的任务。
Future类负责存储和湖区Active Object异步方法的执行结果。get获取异步方法对应的任务的执行结果,set设置异步方法对应的任务执行结果。

Created with Raphaël 2.1.0 client client proxy proxy future future methodRequest methodRequest schedule schedule activationQueue activationQueue servent servent 1asynService() 2create 3create 4enqueue() 5enqueue() 6 7 8 9dispath 10dequeue() 11 12call() 13doSomething() 14 15set() 16 17

例子代码

某电信软件有一个彩信短号模块,其主要功能是实现手机用户给其他手机用于发送彩信是,接收方好吗可以填写为对方的短号。
彩信下发请求处理的入口类

public class MMSDeliveryServlet extends HttpServlet{
    private static final long serialVersionUID = 5886933373599895099L;

    public void doPost(HttpServletRequest req,HttpServletResponse resp)
            throws ServletException,IOException{
        MMSDeliverRequest mmsDeliverReq = this.parseRequest(req.getInputStream());
        Recipient shortNumberRecipient = mmDeliverRep.getRecipient();
        Recipient originalNumberRecipient = null;

        try{
            //将接收方短号转换为长号
            originalNumberRecipient = convertShortNumber(shortNumberRecipient);
        }catch(SQLException e){
            //接收方短号转换为长号时发生数据库异常,触发请求消息的缓存
            AsyncRequestPersistence.getInstance().store(mmsDeliverReq);
            //忽略与模式无关的代码

            resp.setStatus(202);
        }
    }

    prvate MMSDeliverRequest parseRequest(InputStream teqInputStream){
        MMSDeliverRequest mmsDeliverReq = new MMSDeliverRequest();
        //忽略与模式无关的代码
        return mmsDeliverReq;
    }

    private Recipient convertShortNumber(Recipient shortNumberRecipient
            throws SQLException{
        Recipient recipent = null;
        return recipent;
    }
}

AsyncRequestPersistence

public class AsyncRequestPersustence {
    private static final long ONE_MINUTE_INSECONDS = 60;
    private final Longger logger;
    private AtomicLong taskTimeConsumedPerInterval = new AtomicLong(0);
    private AtomicInteger requestSubmittedPerIterval = new AtomicInteger(0);

    //模式角色:ActiveObjice.Servant
    private finalDiskBasedRequestPersistence delegate = new
        diskbasedRequestPersistence();

    //模式角色ActiveObject.Scheduler
    private final ThreadPoolExecutor scheduler;

    //用于保护AsyncRequestPersistence的唯一实例
    private static class iInstanceHolder{
        final static RequestPersistence INSTANCE = new AsyncRequestPersistence();
    }

    //私有构造器
    private AsyncRequestPersistence(){
        logger = Logger.getrLogger(AsyncRequestPersistence.class);
        scheduler = new ThreadPoolExecutor(1,3,60*ONE_MINUTE_INSECONDS,
                TimeUnit.SECONDS,
                //模式角色:ActiveObject。ActivationQueue
                newArrayBlockingQueue(200),new ThreadFactory(){
            @Override
            public Thread newThread(Runnabke r){
                Thread t;
                t = new Thread(r,"AsyncRequestPersistence");
                return t;
            }
        });

        scheduler
            .setRejectedExecutionHandler(new ThreadPoolExecuror.CallerRunsPolicy());

        //启动队列监控定时任务
        Timer moitorTimer = new Timer(true);
        monitorTimer.scheduleAtFixedRate(new TimerTask(){
            @Override
            public void run(){
                if(logger.isInfoEnabled()){
                    logger.info("task count"+requestSubmittedPerIterval
                            +",Queue size:"+scheduler.getQueue().size()
                            +",taskTimeConsumedPerInterval:"
                            +tasjTimeConsumedPerInterval.get()+" ms"    );
                }

                taskTimeConsumePerInterval.set(0);
                requestSubmittedPerInterval.set(0);
            }
        },0,ONE_MINUE_IN_SECONDS*1000);
    }

    //获取类AsyncRequestPersistence的唯一实例
    public static RequestPersistence getInstance(){
        return InstanceHolder.INSTANCE;
    }

    @Override
    public void store(final MMSDeliverRequest request){
        //将对store方法的调用封装成MethodRequest对象,并存入缓冲区
        //模式角色ActiveObject.MethodRequest
        CallablemethodRequest = new Callable(){
            @Override
            pubkuc Boolean call() throws Exception{
                long start = System.currentTimeMillis();
                try{
                    delegate.store(request);
                }finally{
                    taskTimeConsumedPerInterval.addAndGet(
                            System.currentTimeMillis()-start);
                }
                return Boolean.TRUE;
            }
        };
        scheduler.submit(methodRequest);
        requestSubmittedPerIterval.incrementAndGet();
    }
}

RequestPersistence接口

public interface RequestPersistence {
    void store(MMSDeliverRequest request);
}

DiskbasedRequestPersistence类

public class DiskbasedRequestPersistence implements RequestPersistence{
    private final SectionBasedDiskStorage storage = new SectionBasedDiskStorage();
    private final Logger logger = Logger.getLogger(
            DiskbasedRequestPersistence.class);
    @Override
    public void store(MMSDeliverRequest request){
        String[]fileNameParts = storage.apply4Filename(request);
        File file = new File(fileNameParts[0]);
        try{
            ObjectOutputStream objOut = new ObjectOutputStrean(
                    new FileOutputStream(file));
            try{
                objOut.writeObject(request);
            }finally{
                objOut.close();
            }
        }catch(FileNotFoundException e){
            storage.decrementSectionFileCount(fileNameParts[1]);
            logger.error("Failed to store request",e);
        }catch(IOException e){
            storage.decrementSectionFileCount(fileNameParts[1]);
            logger.errir("Failed to store request",e);
        }
    }

    class SectionBaseDiskStorage{
        private Deque sectionNames =new LinkedList();
        //key->value:存储子目录名->子目录下缓存文件计数器
        privateMapsectionFileCountMap
            = new HashMap();
        private int maxFilesPerSection =2000;
        private int maxSectionCount = 100;
        private String storageBaseDir = System.getProperty("user.dir")+"/";

        private final Object sectionLock = new Object();

        public String[] apply4Filename(MMSDeliverRequest request){
            String sectionName;
            int iFileCount;
            boolean need2RemoveSection = false;
            String[] fileName =new String[2];
            synchronized(sectionLock){
                sectionName = this.getSectionName();
                AtomicInteger fileCount;
                fileCount = sectionFileCountMap.get(sectionName);
                iFileCount = fileCount.get();
                //当前存储子目录已满
                if(iFileCount>=maxFilesPerSection){
                    if(sectionNames.size() >= maxSectionCount){
                        need2RemoveSection = true;
                    }
                    //创建新的存储子目录
                    sectionName = this.makeNewSectionDir();
                    fileCount = sectionFileCountMap.get(sectionName);
                }
                ifFileCount = fileCount.addAndGet(1);

            }
            fileName[0] = storageBaseDir + "/" + sectionName + "/"
            + new DicimalFormat("0000").format(iFileCount) + "-"
            + request.getTimeStamp().getTime/1000 + "-"
            + request.getExpiry();
            + ".rq";
        filename[1] = sectionName;

        if(need2RomoveSection){
            //删除最老的存储子目录
            String oldestSectionName = sectionNames.removeFirst();
            this.removeSection(oldestSectionName);
        }
        return fileName;    
        }

        public void decrementSectionFileCount(String sectionName){
            AtomicInteger fileCount = sectionFileCountMap.get(sectionName);
            if(null != fileCount){
                fileCount.decrementAndGet();
            }
        }

        private boolean removeSection(String sectionName){
            boolean result =trus;
            File dir = new File(storageBaseDir + "/" + sectionName);
            for(File file:dir.listFiles()){
                result = result && file.delete();
            }
            result = result && dir.delete();
            return result;
        }

        private String getSectionName(){
            String sectionName;

            if(sectionNames.isEmpty()){
                sectionName = this.makeNewSectionDir();
            }else{
                sectionName = sectionNames.getLast();
            }
            return sectionName;
        }

        private String makeNewSectionDir(){
            String sectionName;
            SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
            sectionName = sdf.format(new Date);
            File dit = new File(storageBaseDir + "/" + sectionName);
            if(dir.mkdir()){
                sectionNames.addLast(sectionName);
                sectionFileCountMap.put(sectonName,new AtomicInteger(0));
            }else{
                throw new RuntimneException("Cannot create sectiojn dir" +
                        sectionName);
            }
            return sectionName;
        }
    }
}

模式的评价与实现考量

Active Object通过讲发放的调用与执行分离,实现了异步变成,有利于提高并发性,从而提高系统的吞吐率。
Active Objecet模式还有个好处是它可以将任务的提交和任务的执行策略分离,降低了系统的耦合性。
但是模式的执行会会有以下的问题需要解决

  1. 采用什么顺序:FIFO、LIFO或者有优先级?
  2. 多少个任务可以并发执行
  3. 多少个任务可以被排队等待执行古国有任务由于系统过载被拒绝,此时哪个任务该被选中为牺牲品,应用程序改如何被通知到?
  4. 任务执行钱、执行后需要执行哪些操作?
    对于这些问题,可以有一下几个处理的策略
  5. 错误隔离
  6. 缓冲区监控
  7. 缓冲区饱和处理策略
  8. scheduler空闲工作者线程清理

你可能感兴趣的:(多线程,java,多线程,设计模式)