为了账号安全,请及时绑定邮箱和手机立即绑定

我应该如何设计这个程序?

我应该如何设计这个程序?

开满天机 2022-06-30 19:03:08
我正在用 Java 编写程序。图片不言自明——main 方法产生三个线程。SAX 处理器处理输入的 XML 文件,生成 JAXB 对象并将它们放入 guava 缓存中。Guava 缓存由另一个线程处理。每当任何对象进入缓存时,该线程都会通知第三个线程,即 MDL 生成器(它关联类似的 JAXB 对象,将它们互连并生成另一个 XML 文件,称为 MDL)。我为主要课程编写了以下代码 -package test;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class MainClass {    public static void main(String args[]) {        ExecutorService xMLService = Executors.newFixedThreadPool(1);        xMLService.execute(new XMLProcessor());        ExecutorService cacheService = Executors.newFixedThreadPool(1);        cacheService.execute(new CacheProcessor());        ExecutorService mdlService = Executors.newFixedThreadPool(1);        mdlService.execute(new MDLProcessor());        xMLService.shutdown();        cacheService.shutdown();        mDLService.shutdown();    }}但是现在我对如何在线程之间传递对象以及如何在新对象进入缓存时通知 MDL 生成器有疑问。在 Java 旧线程模型中,我们可以使用 notify(),但我想使用当前的 ExecutorService。并且有异步回调。所以我想知道如何设计这个框架。如何传递对象并通知线程?我们将缓存对象保存在 HashMap 中,并且 CacheService 线程需要将密钥传递给 MDLService。那么我应该使用哪种模式?
查看完整描述

3 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

如何传递对象并通知线程?我们将缓存对象保存在 HashMap 中,并且 CacheService 线程需要将密钥传递给 MDLService。那么我应该使用哪种模式?

在我看来,你有 1 个线程太多了。XML 读取线程和 MDL 写入是有意义的,但是仅将内容放入内存缓存的线程似乎太复杂了。如果 MDL 生成器需要使用 Guava 缓存,那么它应该“拥有”缓存并将内容粘贴到其中。

这样就剩下 1 个输入 SAX 处理器线程和一个输出 MDL 生成器线程。好的。要连接两者,我会使用BlockingQueue类似的LinkedBlockingQueue. 您可能希望也可能不希望对队列设置大小限制,具体取决于读取是否比写入快以及您的工作中有多少记录。

所以你的主线程将创建BlockingQueue然后将它传递给输入和输出线程。SAX 输入线程调用put()队列,MDL 输出线程调用take()将对象放入 Guava 缓存,然后生成 MDL。

希望这可以帮助。


查看完整回答
反对 回复 2022-06-30
?
Helenr

TA贡献1780条经验 获得超4个赞

由于您使用的是 Guava Cache,因此您可以使用 Guava AsyncEventBus 在任务之间调度消息,并取消三个单独的专用 ExecutorServices。



查看完整回答
反对 回复 2022-06-30
?
HUWWW

TA贡献1874条经验 获得超12个赞

这是上述情况的示例实现。请注意,即使没有 Guava 缓存也可以实现,正如其他一些回复的人所提到的那样;尽管如此,我认为 Nirmalaya 要求它可能是有正当理由的。我可以想到的一个这样的原因是将缓存溢出到存储设备或数据库,以节省运行时内存。


员工记录.xml


<?xml version="1.0" encoding="UTF-8"?>

<Employees>

    <Employee id="1">

        <name>Thomas</name>

    </Employee>

    <Employee id="2">

        <name>Lisa</name>

    </Employee>

    <Employee id="3">

        <name>Ronald</name>

    </Employee>

    <Employee id="4">

        <name>Erica</name>

    </Employee>

</Employees>

Employee.java


package com.technoroy.examples.guava;


/**

 * A value holder POJO implementation for Employee records

 * @author Rahul R

 *

 */

class Employee {

    private Integer id = null;

    private String name = null;


    public Employee() {

        super();

    }


    public Employee(Integer id, String name) {

        super();

        this.id = id;

        this.name = name;

    }


    public Integer getId() {

        return id;

    }


    public void setId(Integer id) {

        this.id = id;

    }


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }


    @Override

    public String toString() {

        return "Employee [id=" + id + ", name=" + name + "]";

    }

}

GuavaCacheProcessor.java


package com.technoroy.examples.guava;


import java.io.IOException;

import java.io.InputStream;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.LinkedBlockingQueue;


import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;


import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;


import com.google.common.cache.Cache;

import com.google.common.cache.CacheBuilder;


/**

 * The primary executable class

 * 

 * @author Rahul R

 *

 */

public class GuavaCacheProcessor {

    private final static BlockingQueue<Integer> notificationQueue = new LinkedBlockingQueue<>();


    public static void main(String... arguments) {

        Runnable xmlProcessor = new Runnable() {

            public void run() {

                parseDataFile();

            }

        };


        Runnable mdlGenerator = new Runnable() {

            public void run() {

                try {

                    while (true) {

                        Integer id = notificationQueue.take();

                        Employee record = ApplicationCacheUtil.getRecord(id);

                        generateContent(record);

                    }

                } catch (InterruptedException e) {

                    Thread.currentThread().interrupt();

                }

            }

        };


        ExecutorService executorService = Executors.newFixedThreadPool(2);

        executorService.submit(xmlProcessor);

        executorService.submit(mdlGenerator);

    }


    public static void generateContent(Employee employee) {

        System.out.println(employee);

    }


    public static void parseDataFile() {

        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();

        InputStream dataInputStream = GuavaCacheProcessor.class.getResourceAsStream("employee-records.xml");


        try {

            SAXParser saxParser = saxParserFactory.newSAXParser();

            saxParser.parse(dataInputStream, new DefaultHandler() {

                private Employee employee = null;

                private StringBuilder elementValue = null;


                @Override

                public void startElement(String uri, String localName, String qName, Attributes attributes)

                        throws SAXException {

                    if (qName.equalsIgnoreCase("Employee")) {

                        employee = new Employee();


                        String id = attributes.getValue("id");

                        if (id.matches("-?\\d+(\\.\\d+)?")) {

                            employee.setId(Integer.valueOf(id));

                        }

                    }


                    elementValue = new StringBuilder();

                }


                @Override

                public void characters(char ch[], int start, int length) throws SAXException {

                    if (elementValue != null) {

                        elementValue.append(new String(ch, start, length));

                    }

                }


                @Override

                public void endElement(String uri, String localName, String qName) throws SAXException {

                    if (qName.equalsIgnoreCase("name")) {

                        if (employee != null && elementValue != null) {

                            employee.setName(elementValue.toString());

                        }

                    } else if (qName.equalsIgnoreCase("Employee")) {

                        ApplicationCacheUtil.putRecord(employee.getId(), employee);

                        try {

                            notificationQueue.put(employee.getId());

                        } catch (InterruptedException e) {

                            e.printStackTrace();

                        }

                    }


                    elementValue = null;

                }

            });

        } catch (ParserConfigurationException | SAXException | IOException e) {

            e.printStackTrace();

        }

    }

}


/**

 * The Cache utilities class, that initializes and returns a handle to the

 * cache.

 * 

 * @author Rahul R

 *

 */

class ApplicationCacheUtil {

    private static Cache<Integer, Employee> cache = CacheBuilder.newBuilder().build();


    public static Cache<Integer, Employee> getCache() {

        return cache;

    }


    public static void putRecord(Integer key, Employee value) {

        cache.put(key, value);

    }


    public static Employee getRecord(Integer key) {

        return cache.getIfPresent(key);

    }

}



查看完整回答
反对 回复 2022-06-30
  • 3 回答
  • 0 关注
  • 109 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信