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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30024821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 16:19:42  来源:igfitidea点击:

Print 1 to 100 using 10 threads in java

javamultithreading

提问by Vivek

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

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

  1. Thread t1should print:

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

    t2should print:

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

    likewise

    t10should print:

    10, 20, 30, ... 100

  2. The final output should be

    1 2 3 .. 100

  1. 线程t1应该打印:

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

    t2应该打印:

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

    同样地

    t10应该打印:

    10, 20, 30, ... 100

  2. 最终输出应该是

    1 2 3 .. 100

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

我试过了,但它在所有 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) 

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);
    }
}

回答by Alexis C.

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 counteris equals to 100you stop all threads to run by breaking the outer loop.

最简单的方法是拥有一个 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;
        }
    }
}

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

给定 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

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.

当线程可以在相对较长的时间窗口内独立于另一个线程工作时,多线程工作得很好,然后如果需要,可能偶尔会聚在一起比较或组合它们的结果。

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.

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

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

所以这里一个简单的循环会更有效,但我可以理解它是出于学习目的。

回答by subin

Here is a solution for the problem.The current thread acquire the lock and we decide if the thread is eligible to execute (printing the number here). If so perform the operation and notify all threads that they can try now. Else wait till its notified by other threads.

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

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();
    }
}

}

}

The output will be
1 printing 1,
2 printing 2,
3 printing 3,
4 printing 4,
5 printing 5,
6 printing 6,
7 printing 7,
8 printing 8,
9 printing 9,
10 printing 10,
1 printing 11,
2 printing 12,
3 printing 13,
4 printing 14,
...
7 printing 97,
8 printing 98,
9 printing 99,
10 printing 100

输出将是
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

回答by user4127

Hope this helps =) Took me an hour to do it.

希望这会有所帮助 =) 我花了一个小时才完成。

package com.xxxx.simpleapp;

import java.util.ArrayList;
import java.util.List;

public class TenThreads {

    public int currentTaskValue = 1;

    public static void main(String[] args) {
        TenThreads monitor = new TenThreads();
        List<ModThread> list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            ModThread modThread = new ModThread(i, monitor);
            list.add(modThread);
        }
        for (ModThread a : list) {
            a.start();
        }
    }

}

class ModThread extends Thread {
    private int modValue;
    private TenThreads monitor;

    public ModThread(int modValue, TenThreads monitor) {
        this.modValue = modValue;
        this.monitor = monitor;
    }

    @Override
    public void run() {
        synchronized (monitor) {
            try {
                while (true) {
                    while (monitor.currentTaskValue % 10 != modValue) {
                        monitor.wait();
                    }

                    if (monitor.currentTaskValue == 101) {
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + " : "
                            + monitor.currentTaskValue + " ,");
                    monitor.currentTaskValue = monitor.currentTaskValue + 1;
                    monitor.notifyAll();
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

output

输出

Thread-1 : 1 ,
Thread-2 : 2 ,
Thread-3 : 3 ,
Thread-4 : 4 ,
Thread-5 : 5 ,
Thread-6 : 6 ,
Thread-7 : 7 ,
Thread-8 : 8 ,
Thread-9 : 9 ,
......
.....
...
Thread-4 : 94 ,
Thread-5 : 95 ,
Thread-6 : 96 ,
Thread-7 : 97 ,
Thread-8 : 98 ,
Thread-9 : 99 ,
Thread-0 : 100 ,

Documentation are intentionally left out for you to figure it out, there are minor bugs too!

文档是故意遗漏给你弄明白的,也有小错误!

回答by artaxerxe

Error is thrown due to calling of waitnot on proper object. wait()should be called on object on which lock is acquired, the one implied by synchronizedkeyword.

由于调用wait不在正确的对象上而引发错误。wait()应该在获得锁的对象上调用,synchronized关键字隐含的那个。

回答by acearch

Well I do not have the code...but the perspective seems to be that there are 100 tasks to be executed each of incrementing a count by 1. So there could be a ThreadPool of say 10 threads and these threads are incrementing the shared count value... Only point to consider is that the Thread pools worker threads have to sequentially execute their tasks one after the other and the thread sequence for the 10 have to be maintained...

好吧,我没有代码......但观点似乎是有 100 个任务要执行,每个任务将计数增加 1。所以可能有一个 ThreadPool 说 10 个线程,这些线程正在增加共享计数价值...唯一需要考虑的是,线程池工作线程必须一个接一个地顺序执行它们的任务,并且必须维护 10 个线程的线程顺序...

回答by Ashutosh Jha

public class BigSequence {
    public static void main(String[] args) {
        BigPrintNum p = new BigPrintNum();
        int max = 20;
        int no_threads = 11;
        for(int i=0;i<no_threads;i++){
            boolean b[] = new boolean[no_threads];
            b[i] = true;
            Thread t = new Thread(new BigPrint(p, max, b,no_threads));
            t.start();
        }
    }
}
class BigPrint implements Runnable {

    int num=0;
    BigPrintNum p;
    int max;
    int no_threads;
    boolean b[];
    public BigPrint(BigPrintNum p,int max,boolean b[],int no_threads){
        this.p = p;
        this.max = max;
        this.b = b;
        this.no_threads = no_threads;
    }
    @Override
    public void run() {
        int n = 0;
        for(int i=0;i<no_threads;i++){
            if(b[i] == true){
                n = i;
                num = i;
            }
        }
        while(num<=max){
            p.print(num, n, no_threads);
            num += no_threads;
        }
    }   
}
class BigPrintNum {
    int turn = 0;
    public synchronized void print(int n,int i,int no_threads){
        while(this.turn != i){
            try{
                wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        System.out.println(i + "th seq = " + n);
        this.turn = (i+1)%no_threads;
        notifyAll();
    }
}

Its a generic one, where we can use any number of threads and use any max value.

它是一个通用的,我们可以使用任意数量的线程并使用任何最大值。

回答by Arjun Gole

public class ThreadSequence 
{

    public static int totalThread;
    public static void main(String[] args) 
    {

        MyLock myLock = new MyLock();
        totalThread = 10;

        for(int i=1;i<=totalThread;i++)
        {
            MyThread myThread = new MyThread(i,myLock);
            myThread.start();
        }

    }

}



class MyLock
{

    public int counter = 0;

}

MyThread Class

MyThread 类

class MyThread extends Thread{

    public MyLock lock;
    public int no;
    public MyThread(int no,MyLock lock)
    {
        super("My Thread No "+no);
        this.no = no;
        this.lock = lock;
    }

    public void run()
    {

        synchronized (lock) 
        {

            while(true)
            {

                while(lock.counter%ThreadSequence.totalThread !=(this.no-1))
                {

                    try 
                    {

                        if(lock.counter > 99)
                        {
                            break;
                        }

                        lock.wait();

                    } catch (InterruptedException e) 
                    {
                        e.printStackTrace();
                    }
                }
                if(lock.counter > 99)
                {
                    break;
                }

                System.out.println("Current Thread "+Thread.currentThread().currentThread()+" --- Current Count "+(lock.counter+1));
                lock.counter = lock.counter +1 ;
                lock.notifyAll();   
            }
        }

    }
}

回答by akhil_mittal

I have written one generic code which will take the number till where you want to print and the number of threads to be used.

我已经写了一个通用代码,它将把数字带到你想要打印的地方以及要使用的线程数。

public class ThreadedPrinting {
    private Object locks[];

    private static class Printer extends Thread {
        int curVal;
        int endVal;
        Object myLock;
        Object nextLock;
        int step;

        public Printer(int startFrom, int endVal, int step, Object myLock, Object nextLock){
            this.curVal = startFrom;
            this.endVal = endVal;
            this.step = step;
            this.myLock = myLock;
            this.nextLock = nextLock;
            this.step = step;
        }

        @Override
        public void run(){
            synchronized(myLock) {
                while (curVal <= endVal) {
                    try {
                        myLock.wait();
                        System.out.println(curVal);
                        curVal += step;
                    }
                    catch(InterruptedException e) {}
                    synchronized(nextLock) {
                        nextLock.notify();
                    }
                }
            }
            synchronized(nextLock) {
                nextLock.notify(); /// this ensures all worker threads exiting at the end
            }
        }
    } // Printer

    public ThreadedPrinting(int maxNum, int threads) {
        locks = new Object[threads];
        int i;
        for(i = 0; i < threads; ++i) locks[i] = new Object();
        for(i = 0; i < threads -1 ; ++i) {
            Printer curPrinter = new Printer(i, maxNum, threads, locks[i], locks[i+1]);
            curPrinter.start();
        }
        Printer lastPrinter = new Printer(i, maxNum, threads, locks[threads - 1], locks[0]);
        lastPrinter.start();
    }

    public void start() {
        synchronized (locks[0]) {
            locks[0].notify();
        }
    }

    public static void main(String[] args) {
        ThreadedPrinting printer = new ThreadedPrinting(1000,7);
        printer.start();
    }
}

The same problem can be solved by usign Phaser as well but the order is not restrictive but will be in round-robin fashion. I have provided the solution for similar problem here.

同样的问题也可以通过使用 Phaser 来解决,但顺序没有限制,而是采用循环方式。我在这里提供了类似问题的解决方案。

回答by Aviad

The simple thing to do is to hold common resource for all of them. Hold a List and every thread will insert into the list, in the end you can sort and print.. If you want them to do it on your order it won't be very effective because you won't need 10 threads to do it..

要做的事情很简单,就是为所有人持有公共资源。持有一个列表,每个线程都会插入到列表中,最后你可以排序和打印。 ..

This way it will be faster and will use 10 threads to do some work, but when everyone finish you still need to do some work

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

回答by Mohan Raj

public class PrintNumbersbyThreads implements Runnable {
    private int i;

    public PrintNumbersbyThreads(int i) {
        this.i = i;
    }

    public static void main(String[] args) {
        PrintNumbersbyThreads p = new PrintNumbersbyThreads(1);
        PrintNumbersbyThreads p2 = new PrintNumbersbyThreads(2);
        PrintNumbersbyThreads p3 = new PrintNumbersbyThreads(3);
        Thread t1 = new Thread(p, "t1");
        Thread t2 = new Thread(p2, "t2");
        Thread t3 = new Thread(p3, "t3");
        t1.start();

        try {
            t1.join();
            t2.start();
            t2.join();
            t3.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        System.out.println("\n" + Thread.currentThread().getName() + " prints  ");
        for (int j = 0; j < 10; j++) {
            System.out.print(i + " ");
            i = i + 10;
        }
    }
}

Written sample code 3 Threads and the output is

编写示例代码3个线程,输出为

t1prints:

t1印刷:

1 11 21 31 41 51 61 71 81 91

1 11 21 31 41 51 61 71 81 91

t2prints:

t2印刷:

2 12 22 32 42 52 62 72 82 92

2 12 22 32 42 52 62 72 82 92

t3prints:

t3印刷:

3 13 23 33 43 53 63 73 83 93

3 13 23 33 43 53 63 73 83 93

Hope this is what you are Looking for?

希望这就是你要找的?