加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-14 05:47:09 所属栏目:Java 来源:网络整理
导读:我是多线程的新手,我得到了一个问题,使用 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中的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模型中,每个线程独立完成其任务,然后合并它们的结果以产生最终结果,例如在合并排序中.但是这假设任务可以很容易地并行化为独立的子任务,这不是这里的情况,因为你的最终输出应该是连续的数字.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读