【发布时间】:2015-06-19 04:57:11
【问题描述】:
当我向外部系统发送请求时,我想实施严格的循环调度。有两个外部系统服务器。第一个请求应该发送到“System1”,第二个请求必须发送到“System2”,下一个请求必须发送到“System1”,依此类推。
由于我只有两台服务器可以向其发送请求,并且我希望在没有任何阻塞和上下文切换的情况下获得最大性能,因此我选择了 AtomicBoolean,因为它使用了 CAS 操作。
我的实现类
1. RoundRobinTest.java
package com.concurrency;
import java.util.Iterator;
public class RoundRobinTest
{
public static void main(String[] args)
{
for (int i = 0; i < 500; i++)
{
new Thread(new RoundRobinLogic()).start();
}
try
{
// Giving a few seconds for the threads to complete
Thread.currentThread().sleep(2000);
Iterator<String> output = RoundRobinLogic.output.iterator();
int i=0;
while (output.hasNext())
{
System.out.println(i+++":"+output.next());
// Sleeping after each out.print
Thread.currentThread().sleep(20);
}
}
catch (Exception ex)
{
// do nothing
}
}
}
2.RoundRobinLogic.java(具有静态 AtomicBoolean 对象的类)
package com.concurrency;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
public class RoundRobinLogic implements Runnable
{
private static AtomicBoolean bool = new AtomicBoolean(true);
public static Queue<String> output = new ConcurrentLinkedDeque<>();
@Override
public void run()
{
if(bool.getAndSet(false))
{
// Sending the request to first system
output.add("Request to System1");
}
else if(!bool.getAndSet(true))
{
// Sending the request to first system
output.add("Request to System2");
}
}
}
输出:
......................
314:Request to System1
315:Request to System2
316:Request to System1
317:Request to System2
318:Request to System1
319:Request to System1
320:Request to System2
321:Request to System2
322:Request to System1
323:Request to System2
324:Request to System1
325:Request to System2
......................
请求 318 和 319 已发送到同一台服务器,在这种情况下 AtomicBoolean 失败。对于我的应用程序,一次可能有 1000-2000 个线程访问共享对象。 从 Java 并发实践中,我看到了以下内容。
在竞争激烈的情况下,锁定往往优于原子变量,但在更现实的情况下 争用级别原子变量优于锁。这是因为锁通过挂起线程对争用做出反应, 减少共享内存总线上的 CPU 使用率和同步流量。 对于低到中等的争用,原子提供了更好的可扩展性;竞争激烈,锁提供 更好地避免争用。 (基于 CAS 的算法在单 CPU 系统上也优于基于锁的算法,因为 CAS 总是在单个 CPU 系统上成功,除非在极少数情况下线程在中间被抢占。 读修改写操作。)
现在我有以下问题。
- 有没有其他高效的非阻塞方式,实现轮询请求发送。
- 在激烈的争论中,AtomicBoolean 是否有可能失败?我的理解是,性能/吞吐量可能会由于激烈的争用而下降。但是在上面的例子中 AtomicBoolean 失败了。为什么 ?
【问题讨论】:
-
你有 1k-2k 线程同时运行?你在多少个处理器上运行它?
-
对
bool和queue的访问不同步,即使它们的状态看起来相互依赖。 -
只是一个想法,如果这真的是你想要的,而且它不是对真正问题的简化,偶尔出现不规则是可以的,因为大量的不规则会均匀化并且您将在两台服务器上获得相同的负载。我喜欢完美,但有时,它根本不需要。现在你可以回去尝试把这件事做好了;)
-
@MickMnemonic 刚刚给了你答案。
-
您的
run方法没有利用 CAS。考虑一下:由于时间问题,可能不会在您的run方法中调用output.add。
标签: java multithreading algorithm atomic atomicboolean