Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print 1 to 100 using 10 threads in java

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. Thread t1 should print:

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

    t2 should print:

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

    likewise

    t10 should print:

    10, 20, 30, ... 100

  2. The final output should be

    1 2 3 .. 100

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);
    }
}
like image 559
Vivek Avatar asked May 04 '15 07:05

Vivek


People also ask

How do you count threads in Java?

The simplest way to see the number of threads in Java is to use a graphical tool like Java VisualVM. Apart from the application threads, Java VisualVM also lists the GC or any other threads used by the application like JMX threads. Monitoring the number of threads is the most basic feature in Java VisualVM.

Can you multi thread in Java?

Java supports multithreading through Thread class. Java Thread allows us to create a lightweight process that executes some tasks. We can create multiple threads in our program and start them.


2 Answers

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

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.

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.

like image 97
Alexis C. Avatar answered Oct 04 '22 05:10

Alexis C.


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

like image 30
subin Avatar answered Oct 04 '22 03:10

subin