我是多线程的新手,我遇到了一个问题,要在 Java 中使用 10 个线程打印 1 到 100,并具有以下约束。
线程
t1
应该打印:1, 11, 21, 31, ... 91
t2
应该打印:2, 12, 22, 32, ... 92
同样
t10
应该打印:10, 20, 30, ... 100
最终输出应该是
1 2 3 .. 100
我试过了,但它在所有 10 个线程中都抛出了以下异常:
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at thread.run(MyThread.java:58)
at java.lang.Thread.run(Unknown Source)
请告诉我如何解决这个问题。
public class MyThread {
/**
* @param args
*/
public static void main(String[] args) {
thread.setSequence();
for(int i = 1; i <= 10; i++) {
Thread t = new Thread(new thread(i));
t.setName(i + "");
t.start();
}
}
}
class thread implements Runnable {
private static HashMap< String, String> sequence = new HashMap<String, String>();
public static final Object lock = new Object();
public static String turn = "1";
private int startValue = 0;
private AtomicInteger counter = new AtomicInteger(1);
public thread(int startValue){
this.startValue = startValue;
}
@Override
public void run() {
while (!counter.equals(10)){
synchronized (lock) {
if(Thread.currentThread().getName().equals(turn)){
System.out.print(startValue + " ");
startValue += 10;
counter.incrementAndGet();
turn = getNextTurn(turn);
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
}
}
}
public static void setSequence(){
for (int i = 1; i <= 10; i++)
if (i == 10)
sequence.put(i + "", 1 + "");
else
sequence.put(i + "", (i + 1) + "");
}
public static String getNextTurn(String currentTurn){
return sequence.get(currentTurn);
}
}
最佳答案
最简单的方法是拥有一个 volatile 变量,每个线程从中读入并根据轮到它更新,否则它只会等到轮到它。当 counter
等于 100
时,您可以通过中断外部循环来停止所有线程的运行。
class MyRunnable implements Runnable {
private static final int LIMIT = 20;
private static volatile int counter = 0;
private int id;
public MyRunnable(int id) {
this.id = id;
}
@Override
public void run() {
outer:
while(counter < LIMIT) {
while (counter % NB_THREADS != id) {
if(counter == LIMIT) break outer;
}
System.out.println("Thread "+Thread.currentThread().getName()+ " printed " + counter);
counter += 1;
}
}
}
给定 20 个和 10 个线程的 LIMIT,它输出:
Thread 0 printed 0
Thread 1 printed 1
Thread 2 printed 2
Thread 3 printed 3
Thread 4 printed 4
Thread 5 printed 5
Thread 6 printed 6
Thread 7 printed 7
Thread 8 printed 8
Thread 9 printed 9
Thread 0 printed 10
Thread 1 printed 11
Thread 2 printed 12
Thread 3 printed 13
Thread 4 printed 14
Thread 5 printed 15
Thread 6 printed 16
Thread 7 printed 17
Thread 8 printed 18
Thread 9 printed 19
当然,这是一种非常糟糕的多线程用法,因为每个线程都在等待轮到它打印和递增计数器。
当线程可以在相对较长的时间窗口内独立于另一个线程工作时,多线程工作得很好,然后可能会在需要时偶尔会面以比较或合并它们的结果。
例如,在 fork-join 模型中,每个线程独立执行其任务,然后合并它们的结果以产生最终结果,例如在合并排序中。但这假设任务可以很容易地并行化为独立的子任务,这里不是这种情况,因为您的最终输出应该是连续的数字。
所以这里一个简单的循环会更有效,但我可以理解这是为了学习目的。
关于java - 在 Java 中使用 10 个线程打印 1 到 100,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30024821/