[英]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.