Java 在多线程中:如何确定哪个线程首先停止
编写一个名为RaceHorse的类来扩展线程。每个赛马都有一个name and run()方法,该方法显示名称5000次。编写一个Java应用程序,实例化2个RaceHorse对象。最后一匹跑完的赛马是失败者 这就是问题所在。 我已经为两个运行线程的类编写了代码 代码如下: 赛马Java 在多线程中:如何确定哪个线程首先停止,java,multithreading,race-condition,Java,Multithreading,Race Condition,编写一个名为RaceHorse的类来扩展线程。每个赛马都有一个name and run()方法,该方法显示名称5000次。编写一个Java应用程序,实例化2个RaceHorse对象。最后一匹跑完的赛马是失败者 这就是问题所在。 我已经为两个运行线程的类编写了代码 代码如下: 赛马 class RaceHorse extends Thread { public String name; public RaceHorse(String name) { this
class RaceHorse extends Thread
{
public String name;
public RaceHorse(String name)
{
this.name = name;
}
public void run()
{
for(int i = 1 ; i <= 5000; i++)
{
System.out.println(i+" "+name);
}
System.out.println(name+" finished.");
}
}
现在我的问题是我无法找到哪一条线先结束,哪一秒结束,即哪匹马赢了,哪匹马输了 公共类堆栈溢出{
公共静态void main(字符串[]args){
赛马obj=新赛马(“Lol”);
赛马obj2=新赛马(“BOL”);
螺纹t=新螺纹(obj);
螺纹t2=新螺纹(obj2);
t、 start();
t2.start();
}
}
类赛马延伸线
{
//公共字符串名称;
公共赛马(字符串名称)
{
这个.setName(name);
}
公开募捐
{
对于(inti=1;i无疑有更好的方法,但有一种方法可能是创建一个类(例如“Trophy”)这是线程安全的,有一个只在第一次调用时返回true的方法“getTrohpy”,并将对Trophy实例的引用传递给两个线程。首先:您的racehouse
对象本身就是线程。您应该能够说obj.start()
而且它也同样有效。因此,完全删除t
和t2
接下来,您将需要一些方法来通知主线程关于获胜者的信息
public void run()
{
... your loop stuff ...
// this is how we're going to do the notification.
Runner.done();
}
public class Runner
{
private static RaceHorse winner = null;
synchronized static void done()
{
// Threads calling this are going to be RaceHorse objects.
// Now, if there isn't already a winner, this RaceHorse is the winner.
if (winner == null) winner = (RaceHorse) Thread.currentThread();
}
public static void main(String[] args)
{
... create the horses ...
// start the horses running
obj.start();
obj2.start();
// wait for them to finish
obj.join();
obj2.join();
System.out.println(winner.name + " wins!");
}
}
我不打算为您编写代码;但是您应该看看要使用的notify
方法(请参阅)
一种方法是:一旦一个线程完成,它将等待()
,等待其他线程通知(或notifyAll()
)
另一个更优雅的解决方案是在共享对象上使用synchronized
块;synchronized(obj)
语句将位于run()的末尾方法。在该语句中,您可以输入一行打印行或任何其他您认为有用的代码,以确定谁赢得了比赛。这将在主选项结束时起作用:
boolean alive1 = true;
boolean alive2 = true;
while (alive1 && alive2) {
alive1 = obj.isAlive();
alive2 = obj2.isAlive();
if (!alive1 && !alive2) {
// Too close to call
}
if (!alive1) {
// obj wins,
}
if (!alive2) {
// obj2 wins,
}
}
正如赵所指出的,racehouse
扩展了Thread
,但你正在为每匹马创建一个新的线程。我会用相反的方法解决它,让racehouse
实现可运行的
其次,使用synchronized
方法的解决方案会起作用,但一般规则是始终在java.util.concurrent
中查找一个类,该类将首先解决问题。可以使用AtomicReference
来解决这个问题,以确保只有一匹马获得奖杯
P>最后,如果主线程以固定的顺序启动马的线程(这取决于VM和启动OS上的新线程的开销),可能会有偏向马1的偏倚。考虑使用所有的马在开始之前等待的信号(例如,<代码> CordTutLabCH < /代码>)。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
public class Runner {
public static void main(String args[]) {
AtomicReference<RaceHorse> winner =
new AtomicReference<RaceHorse>();
CountDownLatch startingPistol = new CountDownLatch(1);
RaceHorse horse1 = new RaceHorse("Lol", startingPistol, winner);
RaceHorse horse2 = new RaceHorse("BOL", startingPistol, winner);
Thread thread1 = new Thread(horse1);
Thread thread2 = new Thread(horse2);
thread1.start();
thread2.start();
startingPistol.countDown();
}
}
class RaceHorse implements Runnable {
private final String name;
private final CountDownLatch startingPistol;
private final AtomicReference<RaceHorse> winner;
public RaceHorse(String name,
CountDownLatch startingPistol,
AtomicReference<RaceHorse> winner)
{
this.name = name;
this.startingPistol = startingPistol;
this.winner = winner;
}
public void run()
{
try {
startingPistol.await();
for(int i = 1 ; i <= 5000; i++)
{
System.out.println(i+" "+name);
}
boolean iWon = winner.compareAndSet(null, this);
System.out.printf("%s %s.%n", name, iWon? "won": "lost");
} catch (InterruptedException ex) {
System.out.printf("%s was assasinated before the race started.%n", name);
Thread.currentThread().interrupt();
}
}
}
import java.util.concurrent.CountDownLatch;
导入java.util.concurrent.AtomicReference;
公开课跑者{
公共静态void main(字符串参数[]){
原子参考=
新原子引用();
倒计时锁启动手枪=新倒计时锁(1);
赛马1=新赛马(“Lol”,起跑手枪,获胜者);
赛马2=新赛马(“BOL”,起跑手枪,获胜者);
螺纹1=新螺纹(1);
螺纹2=新螺纹(2);
thread1.start();
thread2.start();
启动手枪。倒计时();
}
}
类赛马实现可运行{
私有最终字符串名;
私人最后倒计时锁启动手枪;
私人最终原子参考获胜者;
公共赛马(字符串名称,
倒计时锁启动手枪,
原子(参考)
{
this.name=名称;
this.startingPistol=startingPistol;
这个。赢家=赢家;
}
公开募捐
{
试一试{
启动手枪。等待();
对于(int i=1;i我参加聚会迟到了,但我在寻找如何处理多个正在运行的线程的第一个结果时发现了这一点。我认为最简单的方法是使用ArrayBlockingQueue,它会提供类似的结果
public class RaceHorse extends Thread {
private ArrayBlockingQueue<RaceHorse> finishedRaceHorses;
public RaceHorse(String name) {
super(name);
}
public void run() {
for (int i = 1; i <= 50; i++) {
System.out.println(i + " " + getName());
}
System.out.println(getName() + " finished.");
finishedRaceHorses.offer(this);
}
public void setFinishedRaceHorses(ArrayBlockingQueue<RaceHorse> finishedRaceHorses) {
this.finishedRaceHorses = finishedRaceHorses;
}
}
public class Race {
private final List<RaceHorse> raceHorses;
public Race(List<RaceHorse> raceHorses) {
this.raceHorses = raceHorses;
}
public RaceHorse go() throws InterruptedException {
ArrayBlockingQueue<RaceHorse> finishedRaceHorses = new ArrayBlockingQueue<RaceHorse>(raceHorses.size());
for (RaceHorse raceHorse : raceHorses) {
raceHorse.setFinishedRaceHorses(finishedRaceHorses);
raceHorse.start();
}
return finishedRaceHorses.take();
}
}
public class Runner {
public static void main(String args[])
{
RaceHorse horseOne = new RaceHorse("Lol");
RaceHorse horseTwo = new RaceHorse("BOL");
Race race = new Race(Arrays.asList(horseOne, horseTwo));
try {
RaceHorse winner = race.go();
System.out.println("The winner is " + winner.getName());
} catch (InterruptedException e) {
System.out.println("The race was interrupted, maybe by a streaker?");
}
}
}
公共类赛马扩展线程{
专用阵列锁定队列完成牵引马;
公共赛马(字符串名称){
超级(姓名);
}
公开募捐{
对于(int i=1;i我尝试了这个问题,并使用以下代码解决了它。有改进的余地,但对我来说,这个代码工作得非常完美:
1.RacingGame.java
/
包装游戏;
进口野马对象;
导入gamingObject.Race;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.HashMap;
导入java.util.Iterator;
导入java.util.List;
导入java.util.Map;
导入java.util.concurrent.Executor;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公开课比赛{
/**
*@param args
*/
public static Map raceToWinners=new HashMap();
公共静态int currentRace=1;
公共静态布尔trackComplete=false;
私有静态布尔值开始;
私有静态布尔标志=true;
私有静态布尔race6Begin=false;
私有静态布尔race7Begin=false;
私有静态对象互斥=新对象();
私有整数frsthorseinextrace=0;
公共静态void main(字符串[]args)引发InterruptedException{
ExecutorService Executors=Executors.newFixedThreadPool(5);
/*
*进行前5场比赛的逻辑(总马数/总赛道)
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
public class Runner {
public static void main(String args[]) {
AtomicReference<RaceHorse> winner =
new AtomicReference<RaceHorse>();
CountDownLatch startingPistol = new CountDownLatch(1);
RaceHorse horse1 = new RaceHorse("Lol", startingPistol, winner);
RaceHorse horse2 = new RaceHorse("BOL", startingPistol, winner);
Thread thread1 = new Thread(horse1);
Thread thread2 = new Thread(horse2);
thread1.start();
thread2.start();
startingPistol.countDown();
}
}
class RaceHorse implements Runnable {
private final String name;
private final CountDownLatch startingPistol;
private final AtomicReference<RaceHorse> winner;
public RaceHorse(String name,
CountDownLatch startingPistol,
AtomicReference<RaceHorse> winner)
{
this.name = name;
this.startingPistol = startingPistol;
this.winner = winner;
}
public void run()
{
try {
startingPistol.await();
for(int i = 1 ; i <= 5000; i++)
{
System.out.println(i+" "+name);
}
boolean iWon = winner.compareAndSet(null, this);
System.out.printf("%s %s.%n", name, iWon? "won": "lost");
} catch (InterruptedException ex) {
System.out.printf("%s was assasinated before the race started.%n", name);
Thread.currentThread().interrupt();
}
}
}
public class RaceHorse extends Thread {
private ArrayBlockingQueue<RaceHorse> finishedRaceHorses;
public RaceHorse(String name) {
super(name);
}
public void run() {
for (int i = 1; i <= 50; i++) {
System.out.println(i + " " + getName());
}
System.out.println(getName() + " finished.");
finishedRaceHorses.offer(this);
}
public void setFinishedRaceHorses(ArrayBlockingQueue<RaceHorse> finishedRaceHorses) {
this.finishedRaceHorses = finishedRaceHorses;
}
}
public class Race {
private final List<RaceHorse> raceHorses;
public Race(List<RaceHorse> raceHorses) {
this.raceHorses = raceHorses;
}
public RaceHorse go() throws InterruptedException {
ArrayBlockingQueue<RaceHorse> finishedRaceHorses = new ArrayBlockingQueue<RaceHorse>(raceHorses.size());
for (RaceHorse raceHorse : raceHorses) {
raceHorse.setFinishedRaceHorses(finishedRaceHorses);
raceHorse.start();
}
return finishedRaceHorses.take();
}
}
public class Runner {
public static void main(String args[])
{
RaceHorse horseOne = new RaceHorse("Lol");
RaceHorse horseTwo = new RaceHorse("BOL");
Race race = new Race(Arrays.asList(horseOne, horseTwo));
try {
RaceHorse winner = race.go();
System.out.println("The winner is " + winner.getName());
} catch (InterruptedException e) {
System.out.println("The race was interrupted, maybe by a streaker?");
}
}
}
I have tried this problem and solved it using following code. There is room for improvement but for me this code worked perfectly :
1.RacingGame.java
/
package game;
import gamingObject.Horse;
import gamingObject.Race;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RacingGame {
/**
* @param args
*/
public static Map<Integer, List<String>> raceToWinners = new HashMap<Integer, List<String>>();
public static int currentRace = 1;
public static boolean trackComplete = false;
private static boolean newTrackBegin;
private static boolean flag = true;
private static boolean race6Begin = false;
private static boolean race7Begin = false;
private static Object mutex = new Object();
private int frstHorseInNextRace = 0;
public static void main(String[] args) throws InterruptedException {
ExecutorService exeService = Executors.newFixedThreadPool(5);
/*
* Logic to conduct first 5 races (total horses/total track) so here
* total horses = 25 and tracks = 5 hence initial and compolsuary races
*/
RacingGame rg = new RacingGame();
for (int race = 1; race <= 5; race++) {
trackComplete = false;
currentRace = race;
while (!trackComplete) {
rg.startTrack();
}
}
/*
* Before 6th Race lets have right candidate for 6th race
*/
List<String> horseNames = chooseHorsesForRace6();
/*
* Race among 5 tops horses from 5 races
*/
currentRace++;
synchronized (mutex) {
while (!race6Begin) {
race(horseNames);
}
}
/*
* Choose candidates for last race 7
*/
horseNames = chooseHorsesForRace7();
currentRace++;
synchronized (mutex) {
while (!race7Begin) {
race(horseNames);
}
}
printResults();
System.exit(0);
}
private static void printResults() {
// TODO Auto-generated method stub
Iterator<Integer> iter = raceToWinners.keySet().iterator();
while (iter.hasNext()) {
int raceNum = iter.next();
StringBuffer sb = new StringBuffer();
System.out.println("Race" + raceNum + " : ");
List<String> horses = raceToWinners.get(raceNum);
for (int i = 0; i < 3; i++) {
sb.append(horses.get(i));
if (i < 2)
sb.append(",");
}
System.out.print(sb.toString());
System.out.println();
}
}
private static List<String> chooseHorsesForRace7() {
/*
* Adding First horse at first rank among 25 horses
*/
List<String> winners = new ArrayList<String>();
winners.add(raceToWinners.get(6).get(0));
raceToWinners.put(7, winners);
/*
* Taking first horses from races 2 and 3
*/
List<String> finalTrackHorses = new ArrayList<String>();
finalTrackHorses.add(raceToWinners.get(6).get(1));// firstHorse
finalTrackHorses.add(raceToWinners.get(6).get(2));// secondHorse
/*
* Rejecting all horses from race track whose first horses are at 4th
* and 5th rank of race 6
*/
for (int i = 1; i <= 5; i++) {
if (raceToWinners.get(i).contains(winners.get(0))) {
finalTrackHorses.add(raceToWinners.get(i).get(1));// thirdHorse
finalTrackHorses.add(raceToWinners.get(i).get(2));// forth horse
} else if (raceToWinners.get(i).contains(finalTrackHorses.get(1))) {
finalTrackHorses.add(raceToWinners.get(i).get(1));// fifth horse
}
}
return finalTrackHorses;
}
private static void race(List<String> horseNames) throws InterruptedException {
if (currentRace == 6)
race6Begin = true;
else
race7Begin = true;
newTrackBegin = true;
flag = true;
trackComplete = false;
while (flag) {
if (!trackComplete) {
/*
* Create thread for each horse
*
* Here taking slot of 5 horses and keep them running in a
* single loop.
*/
if (newTrackBegin) {
List<String> horses = Arrays.asList(horseNames.get(0),
horseNames.get(1), horseNames.get(2),
horseNames.get(3), horseNames.get(4));
Race r = new Race(horses);
r.start();
}
newTrackBegin = false;
mutex.wait(1);
} else if (trackComplete) {
mutex.notify();
flag = false;
}
}
}
private static List<String> chooseHorsesForRace6() {
List<String> lstHorses = new ArrayList<String>();
for (int i = 1; i <= 5; i++) {
/*
* Take only 1st Position Holders of first 5 races
*/
lstHorses.add(raceToWinners.get(i).get(0));
}
return lstHorses;
}
public Map<Integer, List<String>> getRaceToWinners() {
return raceToWinners;
}
public static synchronized void addTrackWinnerInList(String horseName) {
List<String> horses = raceToWinners.get(currentRace);
if (horses == null) {
List<String> raceHorses = new ArrayList<String>();
raceHorses.add(horseName);
raceToWinners.put(currentRace, raceHorses);
} else {
horses.add(horseName);
raceToWinners.put(currentRace, horses);
}
if (raceToWinners.get(currentRace) != null
&& raceToWinners.get(currentRace).size() == 5) {
trackComplete = true;
}
}
public static boolean isTrackComplete(){
return trackComplete;
}
public void startTrack() throws InterruptedException {
// TODO Auto-generated method stub
synchronized (mutex) {
flag = true;
newTrackBegin = true;
trackComplete = false;
while (!trackComplete) {
/*
* Create thread for each horse
*
* Here taking slot of 5 horses and keep them running in a
* single loop.
*/
if (newTrackBegin) {
List<String> horses = Arrays.asList("Horse"
+ (++frstHorseInNextRace), "Horse"
+ (++frstHorseInNextRace), "Horse"
+ (++frstHorseInNextRace), "Horse"
+ (++frstHorseInNextRace), "Horse"
+ (++frstHorseInNextRace));
Race r = new Race(horses);
r.start();
}
newTrackBegin = false;
}
}
}
}
2.Horse.java
package gamingObject;
import game.RacingGame;
public class Horse extends Thread{
String horseName;
public Horse(String horseName){
this.horseName = horseName;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
RacingGame.addTrackWinnerInList(this.horseName);
}
}
3.Race.java
package gamingObject;
import game.RacingGame;
import java.util.List;
public class Race extends Thread {
List<String> horses;
private boolean flag = true;
private Object obj = new Object();
public Race(List<String> horses) {
this.horses = horses;
}
public void startRace() {
synchronized (obj) {
run();
}
}
@Override
public void run() {
synchronized (obj) {
boolean newTrackBegin = true;
while (!RacingGame.isTrackComplete()) {
/*
* Create thread for each horse
*
* Here taking slot of 5 horses and keep them running in a
* single loop.
*/
if (newTrackBegin) {
Horse h1 = new Horse(horses.get(0));
Horse h2 = new Horse(horses.get(1));
Horse h3 = new Horse(horses.get(2));
Horse h4 = new Horse(horses.get(3));
Horse h5 = new Horse(horses.get(4));
Thread t1 = new Thread(h1);
Thread t2 = new Thread(h2);
Thread t3 = new Thread(h3);
Thread t4 = new Thread(h4);
Thread t5 = new Thread(h5);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
newTrackBegin = false;
}else{
if(!RacingGame.isTrackComplete()){
try {
obj.wait(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
obj.notify();
}
}
}
}
}
}