Java 如何使驼峰路线线程安全?
我有一个骆驼路由,它使用来自ApacheActiveMQ的任务。 当ActiveMQ只有一个使用者时,一切正常 但是当使用者增加到两个或更多时,应用程序的行为就不合适了 这是我的路线:Java 如何使驼峰路线线程安全?,java,thread-safety,apache-camel,activemq,Java,Thread Safety,Apache Camel,Activemq,我有一个骆驼路由,它使用来自ApacheActiveMQ的任务。 当ActiveMQ只有一个使用者时,一切正常 但是当使用者增加到两个或更多时,应用程序的行为就不合适了 这是我的路线: <routeContext id="myRoute" xmlns="http://camel.apache.org/schema/spring"> <route errorHandlerRef="myErrorHandler" id="myErrorRoute">
<routeContext id="myRoute" xmlns="http://camel.apache.org/schema/spring">
<route errorHandlerRef="myErrorHandler" id="myErrorRoute">
<from uri="activemq:queue:{{my.queue}}" />
<log loggingLevel="DEBUG" message="Message received from my queue : ${body}"></log>
<multicast>
<pipeline>
<log loggingLevel="DEBUG" message="Adding to redis : ${body}"></log>
<to uri="spring-redis://localhost:6379?serializer=#stringSerializer" />
</pipeline>
<pipeline>
<transform>
<method ref="insertBean" method="myBatchInsertion"></method>
</transform>
<choice>
<when>
<simple> ${body.size()} == ${properties:my.batch.size}</simple>
<log message="Going to insert my batch in database" />
<to uri="mybatis:batchInsert?statementType=InsertList"></to>
<log message="Inserted in my table : ${in.header.CamelMyBatisResult}"></log>
<choice>
<when>
<simple>${properties:my.write.file} == true</simple>
<bean beanType="com.***.***.processors.InsertToFile"
method="processMy(${exchange}" />
<log message="Going to write to file : ${in.header.CamelFileName}" />
<to uri="file://?fileExist=Append&bufferSize=32768"></to>
</when>
</choice>
</when>
</choice>
</pipeline>
</multicast>
</route>
</routeContext>
以下是豆子:
public class InsertBeanImpl {
public List<Out> myOutList = new CopyOnWriteArrayList<Out>();
public List<Out> myBatchInsertion(Exchange exchange) {
if (myOutList.size() >= myBatchSize) {
Logger.sysLog(LogValues.info,this.getClass().getName(),"Reached max PayLoad size : "+myOutList.size() + " , going to clear batch");
myOutList.clear();
}
Out myOut = exchange.getIn().getBody(Out.class);
Logger.sysLog(LogValues.APP_INFO, this.getClass().getName(), myOut.getMasterId()+" | "+"Adding to batch masterId : "+myOut.getMasterId());
synchronized(myOut){
myOutList.add(myOut);
}
Logger.sysLog(LogValues.info, this.getClass().getName(), "Count of batch : "+myOutList.size());
return myOutList;
}
}
public class SaveToFile {
static String currentFileName = null;
static int iSub = 0;
String path;
String absolutePath;
@Autowired
private Utility utility;
public void processMy(Exchange exchange) {
getFileName(exchange, currentFileNameSub, iSub);
}
public void getFileName(Exchange exchange, String outFile, int i) {
exchange.getIn().setBody(getFromJson(exchange));
path = (String) exchange.getIn().getHeader("path");
Calendar date = null;
date = new GregorianCalendar();
NumberFormat format = NumberFormat.getIntegerInstance();
format.setMinimumIntegerDigits(2);
String pathSuffix = "/" + date.get(Calendar.YEAR) + "/"
+ format.format((date.get(Calendar.MONTH) + 1)) + "/"
+ format.format(date.get(Calendar.DAY_OF_MONTH));
String fileName = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
double megabytes = 100 * 1024 * 1024;
if (outFile != null) {
if (!fileName.equals(outFile.split("_")[0])) {
outFile = null;
i = 0;
}
}
if (outFile == null) {
outFile = fileName + "_" + i;
}
while (new File(path + "/" + pathSuffix + "/" + outFile).length() >= megabytes) {
outFile = fileName + "_" + (++i);
}
absolutePath = path + "/" + pathSuffix + "/" + outFile;
exchange.getIn().setHeader("CamelFileName", absolutePath);
}
public String getFromJson(Exchange exchange) {
synchronized(exchange){
List<Out> body = exchange.getIn().getBody(CopyOnWriteArrayList.class);
Logger.sysLog(LogValues.info, this.getClass().getName(), "body > "+body.size());
String text = "";
for (int i = 0; i < body.size(); i++) {
Out msg = body.get(i);
text = text.concat(utility.convertObjectToJsonStr(msg) + "\n");
}
return text;
}
}
}
由于处理器不同步且线程不安全,因此在多个使用者的情况下,路由无法按预期工作
谁能告诉我如何使我的路由线程安全或同步
我试着让处理器同步,但没用。有没有其他方法可以做到这一点?让处理器线程安全,不要使用太多的同步功能,最好不要使用 要做到这一点,您必须在它们中根本没有可变的实例变量 只有公共属性可以存在,比如某些设置对所有线程都有效,并且在任何方法执行期间都不会更改。这样就不需要使用影响性能的同步机制
Camel中的其他所有内容都是线程安全的,如果处理器实现不是线程安全的,则无法判断Camel是否是线程安全的。确保处理器的线程安全,不要使用太多或更好的同步功能 要做到这一点,您必须在它们中根本没有可变的实例变量 只有公共属性可以存在,比如某些设置对所有线程都有效,并且在任何方法执行期间都不会更改。这样就不需要使用影响性能的同步机制 Camel中的所有其他内容都是线程安全的,如果处理器实现不是线程安全的,则无法判断Camel是否是线程安全的。显然,InsertBeanImpl和SaveToFile都不是线程安全的。通常,Camel路由中使用的bean应该是无状态的,即它们不应该有变量字段 对于InsertBeanImpl,看起来您真正想要做的是将多条消息聚合到一条消息中。对于这样的用例,我将考虑使用CAMEL聚合器(1),这样您就可以更容易地实现线程安全的解决方案。 [1] 对于SaveToFile,我看不出有任何理由将path和absolutePath作为字段。将它们移动到getFileName方法中的局部变量中。显然,InsertBeanImpl和SaveToFile都不是线程安全的。通常,Camel路由中使用的bean应该是无状态的,即它们不应该有变量字段 对于InsertBeanImpl,看起来您真正想要做的是将多条消息聚合到一条消息中。对于这样的用例,我将考虑使用CAMEL聚合器(1),这样您就可以更容易地实现线程安全的解决方案。 [1]
对于SaveToFile,我看不出有任何理由将path和absolutePath作为字段。在getFileName方法中将它们移到局部变量中。我认为您需要准确解释这里的问题所在。如果您的处理器不是线程安全的,那么出现问题不是Camel的错。@AdamHawkes请查看更新的问题。这是我的问题,我如何才能使它线程安全。我一点也不怪Camel:PIt将有助于确定哪些bean/组件出现了问题,然后我们可以深入了解如何解决这些特定的代码段。通过添加com.*.*.**.processors.InsertToFile和insertBean的源代码更新您的问题。我怀疑其中任何一个都不是线程安全的。@TadayoshiSato请查看更新后的问题。我认为您需要准确解释这里的问题是什么。如果您的处理器不是线程安全的,那么出现问题不是Camel的错。@AdamHawkes请查看更新的问题。这是我的问题,我如何才能使它线程安全。我一点也不怪Camel:PIt将有助于确定哪些bean/组件出现了问题,然后我们可以深入了解如何解决这些特定的代码段。通过添加com.*.*.**.processors.InsertToFile和insertBean的源代码更新您的问题。我怀疑其中任何一个都不是线程安全的。@TadayoshiSato请查看更新的问题。