我是Java的初学者,我正在尝试创建一个程序,其中有两个小船"使用多线程在屏幕上互相竞争。我得到了线程部分,可以使两条线在屏幕上相互平行工作。
但是我希望线程在命令的同时启动,所以我找到了CountDownLatch类。我真的不太了解它,但我还是尝试使用它仍然使用一个锁存器,然后让线程等待()直到我调用latch.countDown()
。这一切都运行良好,但我想知道哪个线程首先完成,所以我在main方法中使用了一个计时器和一个if
语句来确定哪个线程/" boat"更快。
然而,我的两个问题是a。由于某种原因,所有内容都打印两次,就像它执行run()两次,以及b。 if语句总是直接转向其他语句,因为它并不认为记录的时间比另一个大。我感觉所有这一切都是由于我使用CountDownLatch造成的一些混乱,但我只是没有经验来解决它。
主要方法:
package practice;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.*;
public class Regatta {
public static void main(String[] args) {
Q timed = new Q();
CountDownLatch latch = new CountDownLatch(0);
Thread t1 = Thread.currentThread();
Scanner scan = new Scanner(System.in);
System.out.println("What team is rower 1 on?");
String roweronename = scan.nextLine();
System.out.println("What team is rower 2 on?");
String rowertwoname = scan.nextLine();
Rower r1 = new Rower(latch, roweronename, timed);
Team2 r2 = new Team2(latch, rowertwoname, timed);
try {
System.out.println("ATTENTION");
t1.sleep(1000);
System.out.println("READY");
t1.sleep(1000);
System.out.println("ROW!");
System.out.println();
System.out.println(roweronename.toUpperCase() + " " + rowertwoname.toUpperCase());
System.out.println("--------------------------------------------");
new Thread(r1).start();
new Thread(r2).start();
latch.countDown();
} catch (InterruptedException e) {
System.out.println("There was an error. Don't click out of the program.");
} catch (Exception e) {
System.out.println("There was another error");
}
try {
r1.t.join();
r2.t.join();
} catch (InterruptedException e) {
System.out.println("interruption error occurred");
}
double finalTimeOne = r1.finalTime;
double finalTimeTwo = r2.finalTime;
if (finalTimeOne < finalTimeTwo) {
System.out.println(roweronename.toUpperCase() + " HAS WON THE RACE!");
} else if (finalTimeTwo < finalTimeOne) {
System.out.println(rowertwoname.toUpperCase() + " HAS WON THE RACE!");
} else
System.out.println("Nobody won");
}
}
带有thread1的子类:
package practice;
import java.util.concurrent.CountDownLatch;
public class Rower implements Runnable {
int meters = 2000;
double startTime, endTime, finalTime;
Thread t;
String name;
CountDownLatch latch;
Q timed;
public Rower(CountDownLatch latch, String name, Q timed) {
this.timed=timed;
this.latch = latch;
this.name = name;
t = new Thread(this, name);
t.start();
System.out.println();
}
public void run() {
try {
latch.await();
double startTime = System.nanoTime();
for (int i = 20; i >= 0; i--) {
System.out.println("|");// each - is 10 meters
Thread.sleep(100);
}
double endTime = System.nanoTime();
double finalTime = endTime - startTime;
timed.getTime(finalTime,name);
} catch (InterruptedException e) {
System.out.println("GET OUT THE WAY!");
System.out.println("race postponed to tommorow");
}
}
}
带有线程2的子类:
package practice;
import java.util.concurrent.CountDownLatch;
public class Team2 implements Runnable {
Q timed=new Q();
int meters = 2000;
double startTime,endTime,finalTime;
Thread t;
String name;
CountDownLatch latch;
public Team2(CountDownLatch latch,String name, Q timed) {
this.timed=timed;
this.latch=latch;
this.name = name;
t = new Thread(this, name);
t.start();
System.out.println();
}
public void run() {
try {
latch.await();
double startTime=System.nanoTime();
for (int i = 20; i >= 0; i--) {
int j=20-i;
System.out.println(" |");// each | is 10 meters
Thread.sleep(100);
}
double endTime=System.nanoTime();
double finalTime=endTime-startTime;
timed.getTime(finalTime, name);
} catch (InterruptedException e) {
System.out.println("GET OUT THE WAY!");
System.out.println("race postponed to tommorow");
}
}
}
使用synchronized方法获取完成时间的类:
package practice;
public class Q {
double finalTime;
String name;
synchronized void getTime(double finalTime, String name){
this.finalTime=finalTime;
this.name=name;
System.out.println("Time of team "+this.name+": "+this.finalTime);//prints twice?
System.out.println("vinay");
}
}
答案 0 :(得分:0)
在Rower(和Team2)类构造函数中,您正在初始化一个全新的Thread,并启动它:
public Rower(CountDownLatch latch, String name, Q timed) {
this.timed=timed;
this.latch = latch;
this.name = name;
//vvvvvvvv THIS IS THE PROBLEM vvvvvvvv//
t = new Thread(this, name);
t.start();
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^//
System.out.println();
}
Rower(或Team2)中不需要线程。在Regatta类中创建的线程足以调用Rower(和Team2)中的“run”方法
// These are all you need to get the boats to race!
new Thread(r1).start();
new Thread(r2).start();
另外,作为旁注:您根本不需要Team2课程......您应该能够通过初始化两个Rower对象来比赛两个不同的船只。
Rower r1 = new Rower(latch, roweronename, timed);
// Changed from Team2 to Rower
Rower r2 = new Rower(latch, rowertwoname, timed);
如果两艘船具有不同的功能,你只需要有两种不同的船级别,例如一艘船的推进力与另一艘不同(划船与帆船,摩托艇等)。在您的情况下,它们看起来基本相同(几乎是复制粘贴)。