在Java中使用10个线程打印1到100 [英] Print 1 to 100 using 10 threads in java

查看:1475
本文介绍了在Java中使用10个线程打印1到100的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是多线程技术的新手,我遇到一个问题,要在Java的以下约束下使用10个线程在1至100的条件下打印出来.

I'm new to muti-threading and I got a question to print 1 to 100 using 10 threads in Java with below constrain.

  1. 线程t1应该打印:

1、11、21、31,... 91

1, 11, 21, 31, ... 91

t2应该打印:

2,12,22,32,... 92

2, 12, 22, 32, ... 92

同样

t10应该打印:

10,20,30,... 100

10, 20, 30, ... 100

  • 最终输出应为

  • The final output should be

    1 2 3 .. 100

    1 2 3 .. 100

  • 我已经尝试过,但是它在所有10个线程中抛出以下异常:

    I have tried it, but it is throwing the following exception in all 10 threads:

    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) 
    

    请让我知道如何解决此问题.

    Please let me know how I can solve this problem.

    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时,您将通过中断外部循环来停止所有线程的运行.

    The simplest way would be to have a volatile variable from which each thread reads in and update according to its turn, otherwise it just waits until his turn. When counter is equals to 100 you stop all threads to run by breaking the outer loop.

    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个线程的限制,它输出:

    Given a LIMIT of 20 and 10 threads, it outputs:

    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
    

    当然,这是多线程的一种非常糟糕的用法,因为每个线程都等待轮流打印并增加计数器.

    Of course, this is a very bad usage of multithreading because each thread waits its turn to print and increment the counter.

    当线程可以在相对较长的时间范围内独立于另一个线程工作时,多线程效果很好,然后可能偶尔会合起来比较或组合它们的结果(如果需要).

    Multithreading works well when threads can work independently of another for relatively long time's window, and then may occasionally meet up to compare or combine their results if needed.

    例如,在fork-join模型中,每个线程独立完成其任务,然后将其结果合并以产生最终结果,例如以合并排序.但这假设该任务可以轻松地并行化为独立的子任务,在这种情况下情况并非如此,因为您的最终输出应该是连续的数字.

    For example in the fork-join model, each thread does its task independently then their results are merged to produce the final outcome, such as in a merge sort for example. But this assume that the task can be easily parallelizable into independant subtasks, which is not the case here because your final output should be consecutive numbers.

    因此,在这里,一个简单的循环会大大提高效率,但我可以理解,这是出于学习目的.

    So here a simple loop would be largely more efficient, but I can understand it's for learning purposes.

    这篇关于在Java中使用10个线程打印1到100的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆