使用 Java 线程计算 1 秒内玩的游戏数量
我想知道我的电脑在 1000 毫秒内可以玩多少个游戏。我之前做过测试,没有使用线程(它播放了13k)。现在我认为我正在使用线程,但我仍然得到相同的结果。由于我对 Java 线程没有太多经验,我认为我做错了什么,但我就是不明白。
提前致谢
public class SpeedTest<T extends BoardGame> implements Runnable
{
public static int gamesPlayed = 0;
private ElapsedTimer timer;
private double maxTime;
private BoardAgent<T> agent;
private BoardGame<T> game;
public SpeedTest(BoardGame<T> game, ElapsedTimer timer, double maxTime, Random rng)
{
this.game = game;
this.timer = timer;
this.maxTime = maxTime;
this.agent = new RandomAgent<T>(rng);
}
@Override
public void run()
{
while (true)
{
BoardGame<T> newBoard = game.copy();
while (!newBoard.isGameOver())
newBoard.makeMove(agent.move(newBoard));
gamesPlayed++;
if (timer.elapsedMilliseconds() > maxTime) {
break;
}
}
}
public static void main(String[] args)
{
Random rng = new Random();
BoardGame<Connect4> game = new Connect4(6, 7);
double maxTime = 1000;
ElapsedTimer timer = new ElapsedTimer();
SpeedTest<Connect4> speedTest1 = new SpeedTest<Connect4>(game, timer, maxTime, rng);
SpeedTest<Connect4> speedTest2 = new SpeedTest<Connect4>(game, timer, maxTime, rng);
Thread t1 = new Thread(speedTest1);
Thread t2 = new Thread(speedTest2);
t1.start();
t2.start();
try {
Thread.sleep((long) maxTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Games: " + SpeedTest.gamesPlayed);
}
}
I want to know how many games my computer can play in 1000 ms. I did the tests before without using Threads (it plays 13k). Now that I think I'm using threads, I still get the same. Since I don't have much experience with Java threads, I assume I'm doing something wrong but I just can't get it.
Thanks in advance
public class SpeedTest<T extends BoardGame> implements Runnable
{
public static int gamesPlayed = 0;
private ElapsedTimer timer;
private double maxTime;
private BoardAgent<T> agent;
private BoardGame<T> game;
public SpeedTest(BoardGame<T> game, ElapsedTimer timer, double maxTime, Random rng)
{
this.game = game;
this.timer = timer;
this.maxTime = maxTime;
this.agent = new RandomAgent<T>(rng);
}
@Override
public void run()
{
while (true)
{
BoardGame<T> newBoard = game.copy();
while (!newBoard.isGameOver())
newBoard.makeMove(agent.move(newBoard));
gamesPlayed++;
if (timer.elapsedMilliseconds() > maxTime) {
break;
}
}
}
public static void main(String[] args)
{
Random rng = new Random();
BoardGame<Connect4> game = new Connect4(6, 7);
double maxTime = 1000;
ElapsedTimer timer = new ElapsedTimer();
SpeedTest<Connect4> speedTest1 = new SpeedTest<Connect4>(game, timer, maxTime, rng);
SpeedTest<Connect4> speedTest2 = new SpeedTest<Connect4>(game, timer, maxTime, rng);
Thread t1 = new Thread(speedTest1);
Thread t2 = new Thread(speedTest2);
t1.start();
t2.start();
try {
Thread.sleep((long) maxTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Games: " + SpeedTest.gamesPlayed);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我怀疑您没有看到任何加速的原因是您的应用程序仅使用 1 个物理处理器。如果它只使用一个处理器,那么两个线程将不会并行运行。相反,处理器将在两个线程之间进行“时间切片”。
对此你能做什么?
在双核等处理器上运行。或者,如果您有支持 HT 的单处理器计算机,请启用 HT。
运行测试的时间较长;例如几分钟。
我建议后者的原因是这可能是 JVM 预热效应。当 JVM 启动一个新应用程序时,它需要在幕后进行大量的类加载和 JIT 编译。这些任务大部分(如果不是完全)是单线程的。在较长的时间内运行测试可以减少“热身”开销对每场“游戏”平均时间的影响。
您应该进行修复以使程序线程安全。更改
为
,然后使用
getAndIncrement()
递增计数器,并使用intValue()
获取其值。 (这比让每个线程维护自己的计数器并在最后对它们求和更简单。)但是,我强烈怀疑这种更改(或@Erik的替代方案)对您所看到的结果几乎没有影响。我现在确信可能是:
I suspect that the reason that you are not seeing any speedup is that your application is only using 1 physical processor. If it is only using one processor, then the two threads won't be running in parallel. Instead, the processor will be "time-slicing" between the two threads.
What can you do about this?
Run on a dual-core etc processor. Or if you have a single processor machine with HT support, enable HT.
Run the test over a longer time; e.g. a number of minutes.
The reason I suggest the latter is that this could be a JVM warmup effect. When a JVM starts a new application, it needs to do a lot of class loading and JIT compilation behind the scenes. These tasks will be largely (if not totally) single-threaded. Running the tests over a longer period of time reduces the contribution of the "warm up" overheads to the average time per "game".
There is a fix that you ought to make to make the program thread-safe. Change
to
and then use
getAndIncrement()
to increment the counter andintValue()
to fetch its value. (This is simpler than having each thread maintain its own counter and summing them at the end.)However, I strongly suspect that this change (or @Erik's alternative) will make little difference to the results you are seeing. I'm now sure it is either:
不要使用静态 int,使用普通成员 int。
在两个线程上调用
.join
而不是睡眠。然后最后添加成员整数。
Don't use a static int, use a normal member int.
Instead of the sleep, call
.join
on both threads.Then finally add the member ints.