在java中使用10个线程打印1到100

前端之家收集整理的这篇文章主要介绍了在java中使用10个线程打印1到100前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我是多线程的新手,我得到了一个问题,使用 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模型中,每个线程独立完成其任务,然后合并它们的结果以产生最终结果,例如在合并排序中.但是这假设任务可以很容易地并行化为独立的子任务,这不是这里的情况,因为你的最终输出应该是连续的数字.

所以这里一个简单的循环在很大程度上会更有效,但我可以理解它是出于学习目的.

猜你在找的Java相关文章