我正在使用Enterprise JavaBeans 3.1开发一个应用程序,并从Socket接收数据。此应用程序充当监听器,一旦收到数据,就会对其进行处理。这个应用程序是单线程的,由于它处理缓慢,应用程序是使用Threads实现的,Threads现在是一个多线程应用程序。通过这样做,应用程序现在运行得更快。
但是,有两个线程,两个线程都访问数据库以插入和更新数据库。我面临并发问题,其中一个线程插入,另一个更新导致问题。为了处理并发性,我添加了一个synchronized块来锁定一个对象,确保执行完整的块。通过这样做,应用程序现在非常慢,就像使用单线程应用程序一样。插入和更新是通过JDBC完成的。
还有其他什么可以做,以便在不降低应用程序速度的情况下快速处理和处理。以下是示例代码:
@Startup
@Singleton
public class Listener {
private ServerSocket serverSocket;
private Socket socket;
private Object object;
private InetAddress server;
@Resource
private ScheduledExecutorService executor;
@PostConstruct
public void init() {
object = new Object();
serverSocket = new ServerSocket("somePortNumber");
Runnable runnable = new Runnable() {
public void run() {
checkDatabase();
if(!isServerActive()) {
// send e-mail
listen();
}
else {
listen();
}
}
};
executor.scheduleAtFixedRate(runnable, 0, 0, TimeUnit.SECONDS);
}
public void listen() {
if(socket == null) {
socket = serverSocket.accept();
}
else if(socket.isClosed()) {
socket = serverSocket.accept();
}
startThread(socket);
}
public void startThread(Socket socket) {
Runnable runnable = new Runnable() {
public void run() {
processMessage(socket);
}
};
new Thread(runnable).start();
}
public void processMessage(Socket socket) {
synchronized(object) {
// build data from Socket
// insert into database message, sentDate
// do other things
// update processDate
}
}
public void checkDatabase() {
synchronized(object) {
// get data and further update
}
}
public boolean isServerActive() {
boolean isActive = true;
if(server == null) {
sever = InetAddress.getByName("serverName");
}
if(!server.isNotReachable(5000)) {
isActive = false;
if(socket != null) {
socket.close();
}
}
return isActive;
}
}
编辑:
Table name: Audit
Message: VARCHAR NOT NULL
SentDate: DATE NOT NULL
ProcessedDate: DATE
AnotherDate: DATE
Query: INSERT INTO AUDIT (message, sentDate, processedDate, receivedDate) VALUES (?, java.sql.Timestamp, null, null)
假设插入记录时没有同步块插入消息和sentDate。另一个线程将执行,导致找到此记录并进一步更新。问题是在初始插入和processedDate之后应该更新,然后应该执行另一个线程。
processMessage()以异步方式通过HTTPS发送数据。
使用Threads的原因之一是因为只有一个数据来自Java。因此,通过引入线程,整套数据将发布到Java。
答案 0 :(得分:1)
即使使用单线程,您也可以通过使用JDBC批处理并在批处理中运行任何事务来获得更快的速度,而不是提交每个插入/更新语句。
在多线程环境中,如果确保没有两个线程同时作用于同一个数据库行,则可以避免并发问题。您可以使用行级锁定来避免多个线程更新同一行。
根据您提供的信息,您无法再获得任何输入。如果您提供有关正在处理的数据的信息,您可能会获得更多想法。
答案 1 :(得分:0)
该应用程序表现为单线程,因为processMessage& checkDatabase方法对同一个类对象有同步块,当前正在侦听的线程将保持锁定,其他线程必须等到消息处理完毕,这将导致应用程序变慢。而不是将synchronized放在两个单独的块中,在类之外创建单独的线程来检查这种情况,然后尝试根据条件单独调用,或者也可以尝试在synchronized块中使用wait()和notifyAll。