我正在使用 JavaFX 8,我有一个奇怪的问题,无论我尝试什么,我都无法让线程同步。
我正在构建的代码需要从屏幕左侧到右侧显示图像。在控制台中提示用户他们想要多少赛车手。当其中一个到达终点线时,所有线程都停止,并且必须在屏幕左侧设置标签,在赛车手比赛的路径上。
线程成功停止,我还没有实现设置标签(如果有人能帮忙的话,这也很好)因为我无法获得正确的线程来将获胜者号码打印到终端。
代码如下:
import java.util.ArrayList;
import java.util.Scanner;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
public class Races extends Application {
Scanner in = new Scanner(System.in);
Stage stage;
Scene scene;
VBox root;
Line finishLine;
Image imgRacer;
boolean keepGoing = true;
public final int DEFAULT_RACERS = 5;
ArrayList<Thread> threadList = new ArrayList<>();
ArrayList<Pane> paneList = new ArrayList<>();
ArrayList<RaceStarter> racerList = new ArrayList<>();
@Override
public void start(Stage stage) throws Exception {
this.stage = stage;
stage.setTitle("Off to the races");
root = new VBox(0);
int numRacers = DEFAULT_RACERS;
imgRacer = new Image(new FileInputStream("embars.gif"));
double imgHeight = imgRacer.getHeight();
double imgWidth = imgRacer.getWidth();
System.out.print("How many racers do you want? (Default 5): ");
if(in.hasNextInt()){
numRacers = in.nextInt();
if(numRacers < 1) numRacers = DEFAULT_RACERS;
}
for(int i = 0; i < numRacers; i++) {
RaceStarter racer = new RaceStarter(i, imgWidth, imgHeight);
paneList.add(racer);
Thread t = new Thread(racer);
threadList.add(t);
t.start();
}
scene = new Scene(root, imgWidth * 20, imgHeight * numRacers);
finishLine = new Line(scene.getWidth() - (imgWidth * 2), 0, scene.getWidth() - (imgWidth * 2), scene.getHeight());
finishLine.setStrokeWidth(2);
finishLine.setStroke(Paint.valueOf("BLACK"));
Pane finishPane = new Pane(finishLine);
root.getChildren().add(finishPane);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
class RaceStarter extends Pane implements Runnable{
int racerNum;
double height, width;
volatile boolean finished = false;
private Object lock = new Object();
public RaceStarter(int racerNum, double width, double height){
this.racerNum = racerNum;
this.width = width;
this.height = height;
}
@Override
public void run() {
System.out.println(Thread.currentThread() + " " + racerNum);
ImageView racer = new ImageView(imgRacer);
Platform.runLater(new Runnable() {
@Override
public void run() {
root.getChildren().add(racer);
}
});
while(keepGoing) {
// System.out.println(name);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
double moveAmount = Math.random() * 5;
Platform.runLater(new Runnable() {
@Override
public void run() {
racer.setTranslateX(racer.getTranslateX() + moveAmount);
}
});
synchronized(paneList){
if(racer.getTranslateX() >= width * 17){
keepGoing = false;
this.finished = true;
System.out.println("Winner is racer #" + (this.racerNum+1));
Label lblWinner = new Label("Winner is racer #" + (this.racerNum+1));
Platform.runLater(new Runnable() {
@Override
public void run() {
paneList.get(racerNum).getChildren().add(0, lblWinner);
}
});
}
}
}
}
}
}```