Java 确保两个线程在一个循环中一个接一个-Android
我有两条这样开始的线Java 确保两个线程在一个循环中一个接一个-Android,java,android,multithreading,Java,Android,Multithreading,我有两条这样开始的线 Thread player1Thread = new Thread(new Player1RunnableManual()); player1Thread.start(); Thread player2Thread = new Thread(new Player2RunnableManual()); player2Thread.start(); 两个玩家,玩家1和玩家2,以不同的方式一次猜100个数字。我们可以忽略他们用来猜测数字的启发式方
Thread player1Thread = new Thread(new Player1RunnableManual());
player1Thread.start();
Thread player2Thread = new Thread(new Player2RunnableManual());
player2Thread.start();
两个玩家,玩家1和玩家2,以不同的方式一次猜100个数字。我们可以忽略他们用来猜测数字的启发式方法。
我需要确保player1先运行,然后player2运行他们player1运行,然后player2再次运行,直到其中一人猜到一个特定的数字(硬编码)
我尝试使用可重入锁,但无法使其工作。player1和player2的可运行项如下所示
如何编写锁实现以使其工作
class Player1RunnableManual implements Runnable {
@Override
public void run() {
while (!gopherFound) {
r = new Random();
final int player1Position = r.nextInt(high - low) + low;
final int outcome = calculateProximity(player1, player1Position);
if (outcome != DISASTER) {
runnableHandler.post(new Runnable() {
@Override
public void run() {
if (holes[player1Position] == 0) {
setPosition(player1, player1Position);
player1Status.setText(outcomesList[outcome]);
}
}
});
if (outcome == SUCCESS) {
gopherFound = true;
winner = "Player 1";
result.setText("Player 1 wins");
break;
}
}
try {
int sleep = r.nextInt(threadHigh - threadLow) + threadLow;
Thread.sleep(sleep);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
}
class Player2RunnableManual implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100 && !gopherFound; i++) {
final int player2Position = i;
final int outcome = calculateProximity(player2, player2Position);
if (outcome != DISASTER) {
Message msg = messageHandler.obtainMessage(player2);
msg.arg1 = player2Position;
msg.arg2 = outcome;
messageHandler.sendMessage(msg);
if (outcome == SUCCESS) {
gopherFound = true;
winner = "Player 2";
result.setText("Player 2 wins");
break;
}
}
try {
int sleep = r.nextInt(threadHigh - threadLow) + threadLow;
Thread.sleep(sleep);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
}
class Player1RunNameManual实现可运行{
@凌驾
公开募捐{
而(!gopherFound){
r=新随机数();
最终整数播放器1位置=r.nextInt(高-低)+低;
最终int结果=计算概率(玩家1,玩家1位置);
如果(结果!=灾难){
runnableHandler.post(新的Runnable(){
@凌驾
公开募捐{
if(孔[Player1位置]==0){
设置位置(播放器1、播放器1位置);
player1Status.setText(结果列表[结果]);
}
}
});
如果(结果==成功){
gopherFound=true;
获胜者=“玩家1”;
result.setText(“玩家1获胜”);
打破
}
}
试一试{
int sleep=r.nextInt(threadHigh-threadLow)+threadLow;
睡眠;
}捕获(例外e){
e、 printStackTrace();
}最后{
}
}
}
}
类player2runnamanual实现可运行{
@凌驾
公开募捐{
对于(int i=1;i为什么不使用单线程执行器?可运行程序将排队
Executor executor = Executors.newSingleThreadExecutor();
while(!gopherFound){
executor.execute(new Player1RunnableManual());
executor.execute(new Player2RunnableManual());
// wait here for the end of the 2 runnables, maybe using Future tasks instead of runnables
}
您可以清理代码,可运行程序内部不能再有“while(!gopherFound)”,但是有了这个,您可以确保可运行程序一个接一个地执行
另一种方法是使用“信号量(1)”,也将使用“获取()”和“释放()”来完成任务方法,但它不能保证先执行哪个线程。要使player1Thread
在player2Thread
之前开始执行player1Thread
您需要在player1Thread
上调用join
,然后再启动player2Thread
。但这意味着player2Thread
将不会启动,除非player2Thread
死亡。
解决方法是,如果您知道player1Thread
启动多长时间后,是否应该player2Thread
启动,然后将该持续时间(转换为毫秒)作为参数传递给player1Thread
或
使用单个线程Executor
并按顺序提交player1runnamanual
和player2runnamanual
。此外,不要忘记关闭Executor
关于您使用可重入锁
的方法可重入锁
是使用同步
块的面向对象等价物。您可以通过将一个块转换为另一个块来进行一些练习。它只执行同步,不保证线程执行顺序。访问共享对象将是决定性的由线程调度程序执行,它有点随机。以确保一个操作将一个接一个地启动。您可以简单地使用ThreadPoolExecutor
。就像下一步一样
final ThreadPoolExecutor executor =
(ThreadPoolExecutor) Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
@Override
public void run() {
// Your action 1
}
});
executor.submit(new Runnable() {
@Override
public void run() {
// Your action 2
}
})