我是多线程的新手,我得到了一个问题,使用
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变量,每个线程从中读入并根据轮到它进行更新,否则它只会等到轮到他.当计数器等于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模型中,每个线程独立完成其任务,然后合并它们的结果以产生最终结果,例如在合并排序中.但是这假设任务可以很容易地并行化为独立的子任务,这不是这里的情况,因为你的最终输出应该是连续的数字.
所以这里一个简单的循环在很大程度上会更有效,但我可以理解它是出于学习目的.