【问题标题】:One producer Multiple Consumer performance一个生产者多个消费者的表现
【发布时间】:2014-09-09 07:06:49
【问题描述】:

我的 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();
} 

【问题讨论】:

标签: java multithreading concurrency consumer synchronisation


【解决方案1】:

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

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

请参阅此SO Post about using a BlockingQueue 了解想法

【讨论】:

    【解决方案2】:

    同步(队列)块之外的东西很少,因为它们是独立的,因此可以并行。

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

    还有

    // ORACLE DB İnsert part    
        if(conn==null)
       { 
         try { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
               ...
        queue.notifyAll();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 2023-03-23
      相关资源
      最近更新 更多