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

Viv*_*vek 7 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) 
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ale*_* C. 6

最简单的方法是有一个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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

给定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
Run Code Online (Sandbox Code Playgroud)

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

当线程可以在相对长时间的窗口中独立工作时,多线程工作得很好,然后在需要时可能偶尔会遇到比较或组合它们的结果.

例如,在fork-join模型中,每个线程独立完成其任务,然后合并它们的结果以产生最终结果,例如在合并排序中.但是这假设任务可以很容易地并行化为独立的子任务,这不是这里的情况,因为你的最终输出应该是连续的数字.

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


小智 5

下面是这个问题的解决方案。当前线程获取锁,我们决定该线程是否有资格执行(在此处打​​印数字)。如果是,则执行操作并通知所有线程他们现在可以尝试。否则等待其他线程通知它。

public class MyThread extends Thread{

//define the Total No.Of Threads needed
public static final int TOTAL_THREADS = 10;

public final static Object obj = new Object();

int threadNo;   
static volatile int counter = 1;

public MyThread(int threadNo){
    this.threadNo= threadNo;
}

@Override
public void run(){

    //in a synchronized block to acquire lock
    synchronized (obj) {

        while(counter<=100){

            /*
             * counter==threadNo => To print the initial numbers till TOTAL_THREADS
             * counter%TOTAL_THREADS == threadNo => e.g 11%10 = 1 -> 1 will print this, 12%10 = 2 ..
             * (counter%TOTAL_THREADS == 0) && (TOTAL_THREADS == threadNo) => 10%10 will be 0, 
             *              and this must be printed by 10 th thread only, ie the highest thread.
             */
            if(counter == threadNo || (counter%TOTAL_THREADS == threadNo) ||
                    ((counter%TOTAL_THREADS == 0) && (TOTAL_THREADS == threadNo))){

                //Display the output as desired
                System.out.println(this.threadNo+" printing"+" "+counter++);

                //notify
                obj.notifyAll();
            }else{

                //current thread not eligible for printing the current counter value, so wait till its notified
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

public static void main (String args[]) {

    /*
     * Creating as many threads as needed.
     */
    for(int i = 1; i<=TOTAL_THREADS;i++){
        MyThread th = new MyThread(i);
        th.start();
    }
}
Run Code Online (Sandbox Code Playgroud)

}

输出将是
1 打印 1,
2 打印 2,
3 打印 3,
4 打印 4,
5 打印 5,
6 打印 6,
7 打印 7,
8 打印 8,
9 打印 9,
10 打印 10,
1 打印 11,
2 打印12,
3 印刷 13,
4 印刷 14,
...
7 印刷 97,
8 印刷 98,
9 印刷 99,
10 印刷 100


Avi*_*iad -1

简单的做法就是为所有人保留公共资源。持有一个列表,每个线程都会插入到列表中,最后你可以排序和打印。如果你想让他们按照你的订单做,它不会很有效,因为你不需要 10 个线程来完成它..

这样速度会更快,并且会使用 10 个线程来完成一些工作,但是当每个人都完成后,你仍然需要做一些工作