创建一个多线程应用程序,它创建多个线程并查询数据库的同一个表
给定输入xml文件格式:
<transliteration>
<element>
<source>about us</source>
</element>
</transliteration>
应用程序读取多个文件并为每个xml文件创建一个多个线程,输出将是另一个格式为
的xml文件<transliteration>
<element>
<source>about us</source>
<target/>
</element>
</transliteration>
下面是线程的运行方法
public void run() {
MultipleDatabaseThread th = new MultipleDatabaseThread();
Map<String,String> map = new HashMap<String,String>();
try
{
Document doc = loadXmlContentToMemory(this.inputString);
XPathExpression expr = null;
XPathFactory xFactory = XPathFactory.newInstance();
XPath xPath = xFactory.newXPath();
expr = xPath.compile("/transliteration/element//source");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
String sourceString = "";
if(nodes.getLength() > 0)
{
for (int i=0; i<nodes.getLength();i++)
{
//System.out.println("Name: "+nodes.item(i).getNodeName() +" Local Name: "+nodes.item(i).getLocalName() +" Value: "+nodes.item(i).getTextContent());
sourceString = nodes.item(i).getTextContent();
map = th.getCompleteStringTransliterate(sourceString, this.language);
if(map.get(sourceString) == null || map.get(sourceString).equals("") || map.get(sourceString).equals(sourceString))
{
map.clear();
map = th.getRecordsFromDatabase(sourceString, language);
Element abc = doc.createElement("target");
String targetString = "";
String[] tokens = sourceString.trim().split("\\s+");
for(int itr=0; itr < tokens.length; itr++)
{
targetString = targetString+" "+map.get(tokens[itr]);
}
abc.setTextContent(targetString.trim());
nodes.item(i).getParentNode().appendChild(abc);
}
else
{
Element abc = doc.createElement("target");
abc.setTextContent(map.get(sourceString));
nodes.item(i).getParentNode().appendChild(abc);
}
}
}
try
{
expr = xPath.compile("/transliteration/element//target");
result = expr.evaluate(doc, XPathConstants.NODESET);
}catch(XPathExpressionException ex)
{ }
NodeList nodesList = (NodeList) result;
for(int i =0;i<nodesList.getLength();i++)
{
System.out.println("Node Name: "+nodesList.item(i).getNodeName()+" Node Value: "+nodesList.item(i).getTextContent());
}
try
{
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StreamResult strResult = new StreamResult(new File(this.inputString+"_out.xml"));
if(doc != null && strResult != null)
{
DOMSource source = new DOMSource(doc);
transformer.transform(source, strResult);
}
}
catch(TransformerException ex)
{
System.out.println(""+ex);
}
catch(TransformerFactoryConfigurationError ex)
{
System.out.println(""+ex);
}
}catch(IOException ex)
{
ex.printStackTrace(System.out);
}
catch(DOMException ex)
{
ex.printStackTrace(System.out);
}
catch(ParserConfigurationException ex)
{
ex.printStackTrace(System.out);
}
catch(SAXException ex)
{
ex.printStackTrace(System.out);
}
catch(XPathExpressionException ex)
{
ex.printStackTrace(System.out);
}
catch(InterruptedException ex)
{
ex.printStackTrace(System.out);
}
}
loadXmlContentToMemory **函数将filename作为输入并加载 文档中的xml内容。
getCompleteStringTransliterate **是一个函数 MulltipleDatabaseThread类,它返回一个map变量 包含source及其traget字符串。
getRecordsFromDatabase **是同一类中的anoher函数 拆分源字符串并再次获取其目标字符串返回map 变量
公共类MultipleDatabaseThread {
public Map<String,String> getCompleteStringTranslate(String inputString, String language) throws InterruptedException
{
Map<String,String> map = new HashMap<String,String>();
synchronized(OutputRecords.getMap())
{
//long startTime = System.currentTimeMillis();
OutputRecords.clearOutputStream();
Thread thCompleteString = new DatabaseThread(inputString, language);
thCompleteString.start();
thCompleteString.join();
map = OutputRecords.getRecords();
//System.out.println("Complete String Time Taken:: "+(System.currentTimeMillis()-startTime));
return map;
}
}
public Map<String,String> getRecordsFromDatabase(String inputString, String language) throws InterruptedException
{
String[] tokens = inputString.split("\\s+");
Map<String,String> map = new HashMap<String,String>();
Thread[] databaseThreads = new Thread[tokens.length];
synchronized(OutputRecords.getMap())
{
//long startTime = System.currentTimeMillis();
OutputRecords.clearOutputStream();
for(int index=0; index < tokens.length; index++)
{
databaseThreads[index] = new DatabaseThread(tokens[index],language);
databaseThreads[index].start();
}
for(int index = 0 ; index < tokens.length; index++)
{
databaseThreads[index].join();
}
map = OutputRecords.getRecords();
//System.out.println("Tokens Time Taken:: "+(System.currentTimeMillis()-startTime));
return map;
}
}
}
这两个函数在OutputRecord类中使用静态/共享映射变量,并生成多个线程,这些线程实际上会调用数据库并填充共享映射变量并返回该变量
但是在执行这个程序时它给出了
Exception in thread "Thread-0" java.lang.NullPointerException
at transliterationthreading.ExecuteOuterThread.run(ExecuteOuterThread.java:66)
在线
if(map.get(sourceString) == null || map.get(sourceString).equals("") || map.get(sourceString).equals(sourceString))
因此一个线程被终止,然后其他线程被完全执行并生成输出文件。我没有遇到问题,任何人都可以解决这个问题。
由于
答案 0 :(得分:0)
我怀疑在评估行
期间地图内容会发生变化if(map.get(sourceString) == null || map.get(sourceString).equals("") || map.get(sourceString).equals(sourceString))
这样,您的null检查会成功,但是从地图获取的新值可能为null。地图未同步!
将此行更改为
String sourceStringValue = map.get(sourceString);
if(sourceStringValue == null || sourceStringValue.equals("") || map.get(sourceString).equals(sourceString))
答案 1 :(得分:0)
感谢所有人的努力
我尝试使用不同的方法解决此问题,方法是不使用静态共享映射并使用ExecutorService和Callable Interface方法
这是我的代码
try
{
doc = loadXmlContentToMemory(this.inputString);
expr = xPath.compile("/transliteration/element//source");
result = expr.evaluate(doc, XPathConstants.NODESET);
}catch(ParserConfigurationException ex)
{
System.out.println("loadXmlError: "+ex.toString());
}
catch(IOException ex)
{
System.out.println("loadXmlError: "+ex.toString());
}
catch(SAXException ex)
{
System.out.println("loadXmlError: "+ex.toString());
}
catch(XPathExpressionException ex)
{
System.out.println("loadXmlError: "+ex.toString());
}
NodeList nodes = (NodeList) result;
String sourceString = "";
if(nodes.getLength() >0)
{
Map<String,String> fileMap = new HashMap<String,String>();
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
for(int index =0; index <nodes.getLength(); index++)
{
sourceString = nodes.item(index).getTextContent();
Callable<Map<String,String>> worker = new MultipleDatabaseCallable(sourceString,language);
Future<Map<String,String>> map = executor.submit(worker);
try
{
//System.out.println(""+Thread.currentThread().getName()+"SourceString:: "+sourceString+"Map: "+map.get().get(sourceString));
fileMap.putAll(map.get());
}catch(InterruptedException ex)
{
System.out.println("future read: "+ex.toString());
}
catch(ExecutionException ex)
{
System.out.println("future read: "+ex.toString());
}
}
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated()) {
}
ExecutorService tokenExecutor = Executors.newFixedThreadPool(NTHREADS);
for(int i =0 ;i<nodes.getLength();i++)
{
sourceString = nodes.item(i).getTextContent();
if(fileMap.get(sourceString) == null || fileMap.get(sourceString).equals("") || fileMap.get(sourceString).equals(sourceString))
{
fileMap.remove(sourceString);
Callable<Map<String,String>> worker = new MultipleTokenCallable(sourceString,language);
Future<Map<String,String>> map = tokenExecutor.submit(worker);
try
{
fileMap.putAll(map.get());
}
catch(InterruptedException ex)
{
System.out.println("Tokenized put Interupted exception: "+ex.toString());
}
catch(ExecutionException ex)
{
System.out.println("Tokenized put Execution exception: "+ex.toString());
ex.printStackTrace(System.out);
}
Element targetElement = doc.createElement("target");
String targetString = "";
String[] tokens = sourceString.trim().split("\\s+");
for(int itr=0; itr < tokens.length; itr++)
{
targetString = targetString+" "+fileMap.get(tokens[itr]);
}
targetElement.setTextContent(targetString.trim());
nodes.item(i).getParentNode().appendChild(targetElement);
//System.out.println(""+Thread.currentThread().getName()+" Target: "+targetString+" Source: "+sourceString);
}
else
{
Element abc = doc.createElement("target");
abc.setTextContent(fileMap.get(sourceString));
nodes.item(i).getParentNode().appendChild(abc);
}
}
tokenExecutor.shutdown();
// Wait until all threads are finish
while (!tokenExecutor.isTerminated()) {
}
try
{
Transformer transformer = TransformerFactory.newInstance().newTransformer();
StreamResult strResult = new StreamResult(new File(this.inputString+"_out.xml"));
if(doc != null && strResult != null)
{
DOMSource source = new DOMSource(doc);
transformer.transform(source, strResult);
}
}
catch(TransformerException ex)
{
System.out.println(""+ex);
}
catch(TransformerFactoryConfigurationError ex)
{
System.out.println(""+ex);
}
}
由于使用此线程生成多个线程,并且所有线程都尝试同时连接到数据库,因此如果并发线程数增加,则可能会产生太多连接错误。因此,您需要维护一个连接池来克服该问题