【发布时间】:2021-12-25 11:49:45
【问题描述】:
我有这段代码,其中每个人都由一个用随机票数据实例化的特殊线程表示,每 5 秒一个 FestivalStatisticsThread 唤醒并从门读取新数据并生成统计信息(有多少人进入并使用什么类型的票)。
public class Main {
public static void main(String[] args) throws InterruptedException {
FestivalGate gate = new FestivalGate();
FestivalAttendeeThread festivalAttendee;
FestivalStatisticsThread statsThread = new FestivalStatisticsThread(gate);
TicketType ticketType;
for (int i = 1; i < 85_000; i++) {
ticketType = TicketType.randomTicket();
festivalAttendee = new FestivalAttendeeThread(ticketType, gate);
festivalAttendee.start();
festivalAttendee.join();
}
statsThread.start();
System.out.println(gate.getValidatedTickets().size());
}
}
问题是我没有找到一种方法来每 5 秒唤醒一次该线程并生成统计信息,我能做到的唯一方法是在最后只生成一次统计信息 第二个问题是我应该在启动festivalAttendee 线程后使用join,否则我存储票证类型的列表不会存储所有票证类型,尽管是同步的。
我还将在这里留下执行我的代码内部工作的代码:
public class FestivalGate {
private List<TicketType> validatedTickets = Collections.synchronizedList(new ArrayList<>());
public List<TicketType> getValidatedTickets() {
return validatedTickets;
}
}
public class FestivalAttendeeThread extends Thread {
TicketType ticketType;
FestivalGate festivalGate;
public FestivalAttendeeThread(TicketType ticketType, FestivalGate festivalGate) {
this.ticketType = ticketType;
this.festivalGate = festivalGate;
}
@Override
public synchronized void run() {
this.festivalGate.getValidatedTickets().add(ticketType);
}
}
public class FestivalStatisticsThread extends Thread {
private int NR_OF_FULL;
private int NR_OF_FULL_VIP;
private int NR_OF_FREE_PASS;
private int NR_OF_ONE_DAY;
private int NR_OF_ONE_DAY_VIP;
private int TOTAL_NUMBER_OF_PEOPLE;
private FestivalGate gate;
public FestivalStatisticsThread(FestivalGate gate) {
this.gate = gate;
}
@Override
public void run() {
calculateNumberOfEachTicketType();
calculateNumberOfPeople();
showStats();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void calculateNumberOfEachTicketType() {
synchronized (this.gate.getValidatedTickets()) {
for (TicketType ticketType : this.gate.getValidatedTickets()) {
if (ticketType.equals(TicketType.FULL)) {
NR_OF_FULL += 1;
} else if (ticketType.equals(TicketType.FULL_VIP)) {
NR_OF_FULL_VIP += 1;
} else if (ticketType.equals(TicketType.FREE_PASS)) {
NR_OF_FREE_PASS += 1;
} else if (ticketType.equals(TicketType.ONE_DAY)) {
NR_OF_ONE_DAY += 1;
} else if (ticketType.equals(TicketType.ONE_DAY_VIP)) {
NR_OF_ONE_DAY_VIP += 1;
}
}
}
}
private void calculateNumberOfPeople() {
TOTAL_NUMBER_OF_PEOPLE +=
NR_OF_FULL +
NR_OF_FULL_VIP +
NR_OF_FREE_PASS +
NR_OF_ONE_DAY +
NR_OF_ONE_DAY_VIP
;
}
public void showStats() {
System.out.println(
TOTAL_NUMBER_OF_PEOPLE + " people have entered " + "\n" +
NR_OF_FULL + " have full tickets " + "\n" +
NR_OF_FREE_PASS + " have free passes " + "\n" +
NR_OF_FULL_VIP + " have full vip passes " + "\n" +
NR_OF_ONE_DAY + " have one day passes " + "\n" +
NR_OF_ONE_DAY_VIP + " have one day vip passes"
);
System.out.println("-----------------------------------------------------------");
System.out.println("-----------------------------------------------------------");
}
}
【问题讨论】:
-
在启动后加入线程将停止执行for循环,直到该线程完成。
-
@Marvin 如果我不使用 join 不是所有类型的票都将存储在数组中
标签: java multithreading concurrency thread-safety