Search code examples
javamultithreadingconcurrencyconsumersynchronization

One producer Multiple Consumer performance


My Java program has Client-Server architecture. In client side i create 1 message and with 10000 thread i send it to server as 10000 client send one message in same time. And in Server class side i have queue with fixed size and every messages first must be put to this queue. Then with multiple channels (or multiple clients) in the same time messages be read. If one channel (or consumer) read one message this message must be deleted from queue. But multiple channels dont give me enough performance than one channel. I think problem in synchronisation of threads. How i can optimise my program? This is my program.

İn client side i have one runnable class (i show important parts of classes) for sending messages

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

And in main client class

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

In server side i write to queue with

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

And read this buffer and send to Oracle DB messages with

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

Multiple channels i create with

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

And finally in server class i am starting 2 threads which ones write to buffer and other one creating channels for reading from Queue and writing to DB.

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

Solution

  • Basically you need to reduce the amount of code that appears in your synchronized {} blocks (as pointed out by @Debasish) and your interaction with the database and file system is what is holding up your release of the lock on the queue, and is preventing other threads from interacting with the queue. From what I can see you only need to synchronize on the "read" and "write" to the queue but all other work should be outside of any synchronized block.

    I recommend you try implementing a BlockingQueue so you don't have to implement the synchronization yourself. Let the Java API do that more efficiently for you.

    See this SO Post about using a BlockingQueue for ideas