2014-06-09 55 views
1

我正在开发Enterprise JavaBeans 3.1中的应用程序,并且我从Socket接收数据。此应用程序充当监听器,一旦收到数据就会被处理。此应用程序是单线程的,由于它处理速度很慢,因此应用程序使用现在是多线程应用程序的线程来实现。通过这样做,应用程序现在运行得更快。Java套接字并发线程太慢

但是,有两个线程,这两个线程访问数据库中插入和更新数据库。我面临一个线程插入和其他更新导致问题的并发问题。为了处理并发性,我添加了一个同步块来锁定一个对象,确保完整的块被执行。通过执行此应用程序现在非常缓慢,因为它与单线程应用程序一样。插入和更新通过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。另一个线程将执行,导致该记录被找到并进一步更新。问题是在初始insert和processedDate应该更新之后,应该执行另一个线程。

的而processMessage()通过HTTPS异步发送数据。

一个使用线程的一个原因是因为只有一个数据块来的Java。因此,通过引入线程,全套数据将传递给Java。即使是单线程

+0

所以你的并发问题是数据库,而不是线程。我建议你发布表格,插入和查询的详细信息。 – EJP

+0

请参阅上面的修改。 – user3189663

回答

1

您可以通过使用JDBC批处理和运行任何交易批左右,而不是提交每一个人的插入/更新语句得到更好的速度。

在多线程环境中,你能避免并发问题,如果你没有确保两个线程在同一时间作用于同一个数据库行。您可以使用行级锁定来避免多个线程更新同一行。

无法为您提供任何有关您提供的信息的更多输入信息。如果您提供有关您正在处理的数据的信息,您可能会有更多的想法。

+0

用于批量插入/更新的+1 –

+0

可以通过JDBC在Java中实现行级锁定吗?数据是消息传入的。我无法给出消息的任何细节,但有客户记录以某种定义的格式发送。问题在于我无法使用JDBC批处理,因为应用程序非常麻烦。这意味着当接收到数据时,它会以非同步的方式处理并通过HTTPS发送。 – user3189663

+1

@ user3189663你被禁止使用Google吗? “JDBC行锁定”上的第二个链接提供了一个很好的指导。 – Ordous

0

该应用程序表现为单线程,因为processMessage & checkDatabase方法在同一个类对象上有同步块,当前正在侦听的线程将持有该锁并且其他线程必须等待,直到处理该消息,这将导致应用程序放慢速度。而不是在两个独立的块中进行同步,在类的外部创建单独的线程,检查此条件并尝试根据条件单独调用,或者也可以在同步块中尝试wait()和notifyAll。

+1

我不明白您的意思。你能举一个例子代码来展示这个吗? – user3189663

+0

你能告诉我情况如何设置? –

+0

请参阅上面的修改。我添加了更多的代码。代码显示条件集。 – user3189663