我的Java程序具有客户端 - 服务器架构。在客户端我创建1条消息并使用10000线程我将其发送到服务器,因为10000客户端同时发送一条消息。在Server类一侧,我有一个固定大小的队列,每个消息首先必须放入这个队列。然后在多个通道(或多个客户端)同时读取消息。如果一个通道(或消费者)读取一条消息,则必须从队列中删除此消息。 但是多个频道不会给我足够的性能而不是一个频道。我认为线程同步问题。我如何优化我的计划?这是我的计划。
İn客户端我有一个可运行的类(我显示类的重要部分)用于发送消息
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个线程,其中一个写入缓冲区,另一个创建从Queue读取并写入DB的通道。
public static void main(String ... args) throws Exception
{
new Server().FromClienttoBuffer();
Thread CreteChannel=new Thread(new CreteChannel(queue,kanalsayi),"CreteChannel" );
CreteChannel.start();
}
答案 0 :(得分:1)
可以从同步(队列)块中删除一些内容,因为它们是独立的,因此可以并行执行。
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();
答案 1 :(得分:1)
基本上你需要减少synchronized {}
块中出现的代码量(正如@Debasish所指出的那样),并且你与数据库和文件系统的交互阻碍了你发布的锁定queue
,阻止其他线程与队列交互。从我所看到的你只需要对队列的“读”和“写”进行同步,但所有其他工作应该在任何同步块之外。
我建议您尝试实施BlockingQueue
,这样您就不必自己实现同步。让Java API为您提高效率。
有关提示
,请参阅此SO Post about using a BlockingQueue