[英]A short Java program that uses multiple threads
我正在嘗試編寫一個使用多個線程的簡短 Java 程序。 我希望主線程每 100 毫秒打印一次“i”。 並且子線程每 1000 毫秒打印一次“測試”。
結果應該是這樣的。
0,1,2,3,4,5,6,7,8,9,Test
10,11,12,13,14,15,16,17,18,19,Test
20,21,22,23,24,25,26,27,28,29,Test
30,31,32,33,34,35,36,37,38,39,Test
40,41,42,43,44,45,46,47,48,49,Test
50,51,52,53,54,55,56,57,58,59,Test
60,61,62,63,64,65,66,67,68,69,Test
70,71,72,73,74,75,76,77,78,79,Test
80,81,82,83,84,85,86,87,88,89,Test
90,91,92,93,94,95,96,97,98,99,Test
但我的結果是這樣的。
0,1,2,3,4,5,6,7,8,9,Test
10,11,12,13,14,15,16,17,18,Test
19,20,21,22,23,24,25,26,27,Test
28,29,30,31,32,33,34,35,36,Test
37,38,39,40,41,42,43,44,45,Test
46,47,48,49,50,51,52,53,54,Test
55,56,57,58,59,60,61,62,63,Test
64,65,66,67,68,69,70,71,72,Test
73,74,75,76,77,78,79,80,81,Test
82,83,84,85,86,87,88,89,90,91,Test
92,93,94,95,96,97,98,99,
這是我的完整代碼:
public class Main {
public static void main(String[] args){
Main.repeatTask(10, 1000);
//print i, then sleep 100ms
for(int i=0;i<100;i++){
System.out.print(i + ",");
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
}
}
//sleep (time)ms then print "Test"
public static void repeatTask(int m, int time) {
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < m; i++) {
try {
Thread.sleep(time);
System.out.println("Test");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
而且我無法更改主要方法。 如何更改我的方法 repeatTask?
這兩個線程是獨立的,也可能跑到不同的JVM,所以沒有什么可以保證你在另一個線程中的sleep()
+ 1000ms
的喚醒將完全匹配主線程100ms
睡眠的10倍。
如果您真的無法更改main
方法,那么您可以創建自己的PrintStream
實現(這是您在System.out
中用於打印的內容):
public static class CustomPrintStream extends PrintStream {
private final AtomicReference<CountDownLatch> latch;
private final int repetitions;
public CustomPrintStream(int repetitions) {
super(System.out);
this.repetitions = repetitions;
this.latch = new AtomicReference<>(new CountDownLatch(repetitions));
}
@Override
public void print(String s) {
super.print(s);
latch.get().countDown();
}
public void waitForLatch() throws InterruptedException {
latch.get().await();
}
public void resetLatch() {
latch.set(new CountDownLatch(repetitions));
}
}
上述實現使用與 JVM 默認情況下相同的System.out
,除了它:
10
)CountDownLatch
的原子引用,該引用在10
處初始化,並在每次觸及0
時在10
處重新初始化。 因此,您修改您的repeatTask
方法如下:
public static void repeatTask(int m, int time) { //<-- note: you don't need time any longer
CustomPrintStream customPrintStream = new CustomPrintStream(m); //<-- create your custom PrintStream with your number of repetitions
System.setOut(customPrintStream); //<-- set it as the out for the JVM
new Thread(() -> {
for (int i = 0; i < m; i++) {
try {
customPrintStream.waitForLatch(); //<-- you wait for the countdown to 10 (the countdown is performed each time the main thread prints a number)
System.out.println("Test"); //<-- hence you print Test
customPrintStream.resetLatch(); //<-- and reset the countdown to 10
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
樣品 output:
0,1,2,3,4,5,6,7,8,9,Test
10,11,12,13,14,15,16,17,18,19,Test
20,21,22,23,24,25,26,27,28,29,Test
30,31,32,33,34,35,36,37,38,39,Test
40,41,42,43,44,45,46,47,48,49,Test
50,51,52,53,54,55,56,57,58,59,Test
60,61,62,63,64,65,66,67,68,69,Test
70,71,72,73,74,75,76,77,78,79,Test
80,81,82,83,84,85,86,87,88,89,Test
90,91,92,93,94,95,96,97,98,99,Test
請注意,這里我不是在等待 1000 毫秒,而是在等待主線程從System.out
的.print()
傳遞 10 次。 這向您保證,如果某事減慢1200ms
等 10 次的總和不是1000ms
,而是例如 1200 毫秒,您的第二個線程仍將等待被調用 10 次之前打印Test
。
免責聲明:我認為上述解決方案是矯枉過正。 如果它是用於概念演示,那么很好,但如果它是真正的生產代碼,我會與
main
的所有者討論以適應實現而不必覆蓋標准PrintStream
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.