我有一个多线程应用程序,其中一个线程将消息发送到另一个线程。等待线程轮询消息并做出反应(处理锁定)。像这样:
等待线程代码:
while(true)
{
if(helloArrived())
System.out.println("Got hello");
if(byeArrived())
System.out.println("Got bye");
if(stopArrived())
break;
}
我想避免这种cpu占用技术,而是使用别的东西。有什么想法吗?
编辑:实际代码如下:
BlockingQueue<Mail> killMeMailbox = new LinkedBlockingQueue<Mail>();
BlockingQueue<Mail> messageMailbox = new LinkedBlockingQueue<Mail>();
public void run()
{
while(true)
{
if(killMeMailbox.size() > 0)
{
break;
}
if(messageMailbox.size() > 0)
{
System.out.println(messageMailbox.poll());
}
}
}
public void receiveMail(Mail mail)
{
//kill
if(mail.from == -1)
{
killMeMailbox.add(0);
}
else
{
//other
try
{
messageMailbox.put(mail);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
答案 0 :(得分:3)
避免这种情况的正确方法是使用java.lang.Object
实现的等待/通知机制,或Java类库提供的更高级别的并发机制之一:
BlockingQueue
接口的类。(选择与您的特定用例最匹配的机制......)
使用Thread.sleep
不是一个好的解决方案。虽然您减少了CPU负载(与轮询循环相比),但另一方面是您降低了响应速度。
我现在正在使用BlockingQueue。但也许我做错了。我刚刚添加了上面的实际代码。你看到我的问题吗?
是的。您正在以一种旨在避免阻止的方式使用队列。这是错误的做法。您应该使用take()
(它将阻止直到条目可用)而不是poll()
,并删除测试队列大小的代码。
您的“killMeMailbox”内容似乎旨在让您停止等待邮件。您应该能够使用Thread.interrupt
实现该功能。 (中断将解锁take()
呼叫...)
答案 1 :(得分:2)
你正在做busy waiting。你永远不应该这样做,因为它会浪费CPU周期。等待某个事件的线程或进程应该在blocked state中。以下是实现此目的的可能方法:
答案 2 :(得分:0)
如果您可以根据任务执行者重新表述您的问题,那么请考虑使用SingleThreadExecutor。如果您需要更具异国情调的东西 - a concurrent queue甚至wait()/notify()。
答案 3 :(得分:-1)
您是否尝试过放置一些Thread.sleep以避免不断执行while循环?它将为你的其他线程释放CPU并避免生猪
http://docs.oracle.com/javase/tutorial/essential/concurrency/sleep.html