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

标签 java multithreading

我是多线程的新手,我遇到了一个问题,要在 Java 中使用 10 个线程打印 1 到 100,并具有以下约束。

  1. 线程 t1 应该打印:

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

    t2 应该打印:

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

    同样

    t10 应该打印:

    10, 20, 30, ... 100

  2. 最终输出应该是

    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/

相关文章:

java - Thread.join() 不起作用

java - 如果我在 Debug模式下启动 tomcat,为什么 tomcat 可以重新加载我修改过的类?

java - 找不到记录器(log4j)的附加程序?

java - 哪些操作取决于 LinkedHashMap 的容量?是否有可用的并发版本?

c++ - C++中的线程池设计

java - 在线程中创建然后使用 JDBC 语句的最佳设计

c# - 静态构造函数和单例类

c - Pthreads - 高内存使用率

java - 检查 String 是否包含 ArrayList 中的单词之一

java - Spring AspectJ 切点