3 回答
TA贡献1784条经验 获得超2个赞
如何传递对象并通知线程?我们将缓存对象保存在 HashMap 中,并且 CacheService 线程需要将密钥传递给 MDLService。那么我应该使用哪种模式?
在我看来,你有 1 个线程太多了。XML 读取线程和 MDL 写入是有意义的,但是仅将内容放入内存缓存的线程似乎太复杂了。如果 MDL 生成器需要使用 Guava 缓存,那么它应该“拥有”缓存并将内容粘贴到其中。
这样就剩下 1 个输入 SAX 处理器线程和一个输出 MDL 生成器线程。好的。要连接两者,我会使用BlockingQueue
类似的LinkedBlockingQueue
. 您可能希望也可能不希望对队列设置大小限制,具体取决于读取是否比写入快以及您的工作中有多少记录。
所以你的主线程将创建BlockingQueue
然后将它传递给输入和输出线程。SAX 输入线程调用put()
队列,MDL 输出线程调用take()
将对象放入 Guava 缓存,然后生成 MDL。
希望这可以帮助。
TA贡献1780条经验 获得超4个赞
由于您使用的是 Guava Cache,因此您可以使用 Guava AsyncEventBus 在任务之间调度消息,并取消三个单独的专用 ExecutorServices。
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);
}
}
添加回答
举报