-1

我的 Java 程序具有客户端-服务器架构。在客户端,我创建了 1 条消息,并使用 10000 个线程将其发送到服务器,因为 10000 个客户端同时发送一条消息。在服务器类端,我有固定大小的队列,每条消息首先必须放入这个队列。然后用多个通道(或多个客户端)在同一时间读取消息。如果一个通道(或消费者)读取一条消息,则必须从队列中删除该消息。但是多个频道并没有比一个频道给我足够的性能。我认为线程同步存在问题。如何优化我的程序?这是我的程序。

在客户端我有一个可运行的类(我显示类的重要部分)用于发送消息

public void run() 
{  
   pw.println(message+numberofmessage);
}

在主要客户类别中

ExecutorService pool = Executors.newFixedThreadPool(axinsayi);
          for(int i=1;i<=countofUser;i++)
          {
            pool.execute(new SendMessagetoServer(pw,message,i));
          }
           pool.shutdownNow(); 

在服务器端,我写入队列

public void run() 
{   
    while (true) 
    {   
        try {if(!input.ready()) continue;} 
        catch (IOException ex) {}

        synchronized (queue) 
        {
            while (queue.size() == buffersize) 
            {
                try 
                {queue.wait();} 
                catch (InterruptedException ex){}
            }
            try {line=input.readLine();} 
            catch (IOException ex) {}
            System.out.println("Entered to buffer : " + line);
            queue.add(line);
            queue.notifyAll();
        }
    }
}

并读取此缓冲区并发送到 Oracle DB 消息

public void run() 
{    
    while (true) 
    {
        synchronized (queue) 
        {
            while (queue.isEmpty()) 
            {
                try {queue.wait();} 
                catch (InterruptedException ex) {}
            }
            line=(String)queue.remove();

        // ORACLE DB İnsert part    
            if(conn==null)
           { 
             try { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
                   conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl",          "HR", "Ilkinpassword");} 
             catch (SQLException ex) {System.out.println("Connection not created");}
           }
           try {String sql = "insert into hr.info values('"+line+"')";
                ps = conn.prepareStatement(sql);
                ps.executeUpdate();
                System.out.println(line + " inserted to DB");} 
            catch (SQLException ex) {System.out.println(line+"cant inserted to DB");}
            try {ps.close();} 
            catch (SQLException ex) {}
            queue.notifyAll();
        }
    }
}

我创建的多个频道

public void run() 
{ 
    for(int i=1;i<=counntofChannel;i++)
    {
      pool.execute(new WriteFromQueuetoDB(queue));
    }
     pool.shutdownNow();
}

最后在服务器类中,我启动了 2 个线程,一个线程写入缓冲区,另一个创建通道以从队列读取并写入数据库。

public static void main(String ... args) throws Exception 
{
  new Server().FromClienttoBuffer();
  Thread CreteChannel=new Thread(new CreteChannel(queue,kanalsayi),"CreteChannel" );
  CreteChannel.start();
} 
4

2 回答 2

1

There are few things that can be out of the synchronized(queue) block, as these are independent and therefore can go in parallel.

 try {line=input.readLine();} 
            catch (IOException ex) {}
            System.out.println("Entered to buffer : " + line);

and also

// ORACLE DB İnsert part    
    if(conn==null)
   { 
     try { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
           ...
    queue.notifyAll();
于 2014-09-09T07:17:29.050 回答
1

基本上,您需要减少出现在synchronized {}块中的代码量(正如@Debasish 所指出的那样),并且您与数据库和文件系统的交互是阻止您释放锁定的queue原因,并阻止其他线程与队列交互。据我所知,您只需要在“读取”和“写入”队列中同步,但所有其他工作都应该在任何同步块之外。

我建议您尝试实现 aBlockingQueue这样您就不必自己实现同步。让 Java API 更有效地为您完成这项工作。

有关使用 BlockingQueue的想法,请参阅此SO Post

于 2014-09-09T13:15:14.773 回答