Lokesh
Lokesh

Reputation: 7940

3 threads to print alternate values in sequence

I am trying to create an implementation where multiple threads print alternate values of sequence. So here thread1 will print 1,4,7 thread2 will print 2,5,8 thread3 will print 3,6,9. I am using Atomic integer and modulo function.

Below implementation works fine in the sense that first thread prints 1,4,7 while second prints 2,5,8 and third prints 3,6,9 but problem is that sequence is not maintained i.e output can be like 1,3,2,4,5,7,8,6,9 while i want sequence to be maintained as proper threads shld print those values. One condition is i don't want to use synchronize. [Just for learning purpose]

import java.util.concurrent.atomic.AtomicInteger;

public class ThreeThreadsOrderedLockLess {

    AtomicInteger sharedOutput = new AtomicInteger(0);

    public static void main(String args[]) {



        ThreeThreadsOrderedLockLess t = new ThreeThreadsOrderedLockLess();



        ThreadTasks t1 = t.new ThreadTasks(0);
        ThreadTasks t2 = t.new ThreadTasks(1);
        ThreadTasks t3 = t.new ThreadTasks(2);

        Thread ts1 = new Thread(t1);
        Thread ts2 = new Thread(t2);
        Thread ts3 = new Thread(t3);
        ts1.start();
        ts2.start();
        ts3.start();

    }

    private class ThreadTasks implements Runnable {

        private final int threadPosition;


        public ThreadTasks(int threadPosition) {
            super();

            this.threadPosition = threadPosition;
        }

        @Override
        public void run() {

            while (sharedOutput.get() < 9) {

                if (sharedOutput.get() % 3 == this.threadPosition) {

                    System.out.println("Printing output for Thread: "
                            + this.threadPosition + "  "
                            + sharedOutput.incrementAndGet());
                }
            }

        }
    }

}

Upvotes: 1

Views: 14905

Answers (15)

public class PrintSeqNumUsingAltThreads {

    public static void main(String[] args) {
        AtomicInteger counter = new AtomicInteger(0);
        int numThreads = 3;

        Thread t1 = new Thread(new SeqNumPrinter(counter, 0, numThreads));
        Thread t2 = new Thread(new SeqNumPrinter(counter, 1, numThreads));
        Thread t3 = new Thread(new SeqNumPrinter(counter, 2, numThreads));

        t1.currentThread().setName("T1");
        t2.currentThread().setName("T2");
        t3.currentThread().setName("T3");

        t1.start();
        t2.start();
        t3.start();
    }
}


public class SeqNumPrinter implements Runnable {

    AtomicInteger atmCounter;
    Integer threadPosition;
    Integer numThreads;

    public SeqNumPrinter(AtomicInteger counter, int position, int numThreads) {
        this.atmCounter = counter;
        this.threadPosition = position;
        this.numThreads = numThreads;
    }

    @Override
    public void run() {
        while (atmCounter.get() < 10) {
            if (atmCounter.get() % numThreads == threadPosition) {
                System.out.println("Printing value : " + atmCounter.getAndIncrement() + ", by thread : " + 
                        Thread.currentThread().getName());
            }
        }
    }
}

Output :

Printing value : 0, by thread : Thread-0
Printing value : 1, by thread : Thread-1
Printing value : 3, by thread : Thread-0
Printing value : 2, by thread : Thread-2
Printing value : 4, by thread : Thread-1
Printing value : 6, by thread : Thread-0
Printing value : 5, by thread : Thread-2
Printing value : 7, by thread : Thread-1
Printing value : 9, by thread : Thread-0
Printing value : 8, by thread : Thread-2

Upvotes: 0

s-radix
s-radix

Reputation: 21

The ThreadSynchronization class can be used to print numbers between 'n' no. of threads in sequence. The logic is to create a common object between each of the consecutive threads and use 'wait', 'notify' to print the numbers in sequence. Note: Last thread will share an object with the first thread.

You can change the 'maxThreads' value to increase or decrease the number of thread in the program before running it.

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

public class ThreadSynchronization {

    public static int i = 1;
    public static final int maxThreads = 10;

    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < maxThreads; i++) {
            list.add(new Object());
        }
        Object currObject = list.get(maxThreads - 1);
        for (int i = 0; i < maxThreads; i++) {
            Object nextObject = list.get(i);
            RunnableClass1 a = new RunnableClass1(currObject, nextObject, i == 0 ? true : false);
            Thread th = new Thread(a);
            th.setName("Thread - " + (i + 1));
            th.start();
            currObject = list.get(i);
        }
    }

}

class RunnableClass implements Runnable {

    private Object currObject;
    private Object nextObject;
    private boolean firstThread;

    public RunnableClass(Object currObject, Object nextObject, boolean first) {
        this.currObject = currObject;
        this.nextObject = nextObject;
        this.firstThread = first;
    }

    @Override
    public void run() {
        int i = 0;
        try {
            if (firstThread) {
                Thread.sleep(5000);
                firstThread = false;
                System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                synchronized (nextObject) {
                    nextObject.notify();
                }
            }
            while (i++ < Integer.MAX_VALUE) {
                synchronized (currObject) {
                    currObject.wait();
                }
                System.out.println(Thread.currentThread().getName() + " - " + ThreadSynchronization.i++);
                Thread.sleep(1000);
                synchronized (nextObject) {
                    nextObject.notify();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Upvotes: 0

Kumar Ashutosh
Kumar Ashutosh

Reputation: 1244

public class PrintThreadsInSerial {
    public static void main(String[] args) {
    Thread t = new Thread(new Job());
    t.start();
    }
}

class Job implements Runnable {
    @Override
    public void run() {
     while (true) {
        for (int i = 1; i <= 3; i++) {
         System.out.println(i);
        }
     }
    }
}

Upvotes: 0

Nilesh N
Nilesh N

Reputation: 1

You can use below code to print sequential numbers using multiple threads -

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ThreadCall extends Thread {

    private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
    private ThreadCall next;

    public void setNext(ThreadCall t) {
        this.next = t;
    }

    public void addElBQ(int a) {
        this.bq.add(a);
    }

    public ThreadCall(String name) {
        this.setName(name);
    }

    @Override
    public void run() {
        int x = 0;
        while(true) {
            try {
                x = 0;
                x = bq.take();
                if (x!=0) {
                    System.out.println(Thread.currentThread().getName() + " =>" + x);
                    if (x >= 100) System.exit(0); // Need to stop all running threads
                    next.addElBQ(x+1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        int THREAD_COUNT = 10;
        List<ThreadCall> listThread = new ArrayList<>();

        for (int i=1; i<=THREAD_COUNT; i++) {
            listThread.add(new ThreadCall("Thread " + i));
        }

        for (int i = 0; i < listThread.size(); i++) {
            if (i == listThread.size()-1) {
                listThread.get(i).setNext(listThread.get(0));
            }
            else listThread.get(i).setNext(listThread.get(i+1));
        }

        listThread.get(0).addElBQ(1);

        for (int i = 0; i < listThread.size(); i++) {
            listThread.get(i).start();
        }
    }
}

Hope this will resolve your problem.

Upvotes: 0

Nitin
Nitin

Reputation: 19

I am putting code to print 1-100 using 5 threads. One can use any number of thread to print output in round robin fashion.

Basic concept is to lock one object and notify other for executing the printing of value.

public class PrintOneToHundredUsing5Threads {

    public static void main(String[] args) {
        List<Object> objList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            objList.add(new Object());
        }
        for (int i = 0; i < 5; i++) {
            Thread t = new Thread(new PrintThread(objList.get(i), objList.get((i + 1) % 5)));
            t.setName("Thread" + i);
            t.start();
        }
    }

}

class PrintThread implements Runnable {
    Object current;
    Object next;
    volatile static int i = 1;

    PrintThread(Object cur, Object next) {
        this.current = cur;
        this.next = next;
    }

    @Override
    public void run() {
        for (; i <= 100;) {
            synchronized (current) {
                synchronized (next) {
                    next.notify();
                    System.out.println(Thread.currentThread().getName() + " Value : " + i++);
                }
                try {
                    current.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }

}

Upvotes: 0

arora
arora

Reputation: 11

package threeThread;

class Task implements Runnable {

  String message;
  ThreeThread lock;
  int i = 0;
  int p;

  public Task(String text, ThreeThread obj, int p) {
    message = text;
    this.lock = obj;
    this.p = p;
  }

  @Override
  public void run() {

    while(true) {
        synchronized (lock) {

            while(!((lock.status % 3) == 0) && p == 1){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            while(!((lock.status % 3) == 1) && p == 2){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            while(!((lock.status % 3) == 2) && p == 3){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("thread: " + p + " : " + message);
            lock.status++;
            lock.notifyAll();
        }
    }
  }
}

public class ThreeThread {

  volatile int status = 0;
  public static void main(String[] args) {

    ThreeThread lock = new ThreeThread();
    Thread t1 = new Thread(new Task("Hello", lock,1));
    Thread t2 = new Thread(new Task("Good", lock,2));
    Thread t3 = new Thread(new Task("Morning", lock,3));
    t1.start();
    t2.start();
    t3.start();
  }

}

Upvotes: 0

Gopinath
Gopinath

Reputation: 49

Below code snippet will print numbers in sequence and all threads will be terminated gracefully after the task. Used AtomicInteger, which is thread-safe for printing the numbers and same logic can be applied to print as till any number with any number of threads.

 
    import java.util.concurrent.atomic.AtomicInteger;

    public class PrintNumSequence
    {
        public static void main(String[] args)
        {
          AtomicInteger atomicInteger = new AtomicInteger(0);
          new NumPrinter(atomicInteger, 0).start();// thread0
          new NumPrinter(atomicInteger, 1).start();// thread1
          new NumPrinter(atomicInteger, 2).start();// thread2

        }
    }

    class NumPrinter extends Thread
    {

        private AtomicInteger   atomicInteger;
        private int             threadNum;

       public NumPrinter(AtomicInteger atomicInteger, int threadNum)
       {
        this.atomicInteger = atomicInteger;
        this.threadNum = threadNum;
       }

       @Override
       public void run()
       {
        int num = atomicInteger.intValue();
        do
        {
            synchronized (atomicInteger)
            {
                num = atomicInteger.intValue();
                // If number is 9 then stop.
                if (num > 9)
                {
                    atomicInteger.notifyAll();
                    break;
                }
                // 3 is number of threads
                if ((num % 3) == threadNum)
                {
                    System.out.println("Thread-" + threadNum + " -->" + num);
                    num = atomicInteger.incrementAndGet();

                }
                atomicInteger.notifyAll();
                try
                {
                    atomicInteger.wait();
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
         } while (true);
       }
     }

Upvotes: 2

Drona
Drona

Reputation: 7234

This can be better implemented using blocking queues. Define a worker holding a blocking queue. The workers waits on the queue until it receives a number in it. It prints the number it receives, increments it and passes it on to the next worker in the chain. Refer here for the full solution.

Upvotes: 0

neeraj kumar
neeraj kumar

Reputation: 21

import java.util.concurrent.atomic.AtomicInteger; 
 public class Print123456789 {

public static void main(String[] args) {
    print p1 = new print(0);
    print p2 = new print(1);
    print p3 = new print(2);

    Thread t1 = new Thread(p1);
    Thread t2 = new Thread(p2);
    Thread t3 = new Thread(p3);

    t1.start();
    t2.start();t3.start();


}

}



class print implements Runnable {
private int threadNumber;
private static AtomicInteger atomicInteger = new AtomicInteger(0);
public print(int threadNumber) {
    super();
    this.threadNumber = threadNumber;
}

public void run(){
    try{
    while(atomicInteger.get() < 10){
        synchronized (atomicInteger) {

            if((atomicInteger.get()%3) == this.threadNumber){
                System.out.println(atomicInteger.getAndIncrement() + " Thread :" + this.threadNumber );
                atomicInteger.notifyAll();
                }
            else
                atomicInteger.wait();
        }
    }
    }catch(InterruptedException e)
    {
        e.printStackTrace();
    }
}


}

Upvotes: 0

ManishKr
ManishKr

Reputation: 201

    package test.mk.thread;
import java.util.concurrent.atomic.AtomicInteger;

public class MkThread2 {
    int nextThreadToRun = 1;
    int[] arr = {1,2,3,4,5,6,7,8,9,10,11};
    AtomicInteger nextArrayIndex = new AtomicInteger(0);
    boolean token = true;

    public static void main(String[] args) {
        MkThread2 mkThread = new MkThread2();
        Thread t1 = new Thread(new Worker2(1, mkThread));
        Thread t2 =  new Thread(new Worker2(2, mkThread));
        Thread t3 =  new Thread(new Worker2(3, mkThread));
        t1.start();
        t2.start();
        t3.start();
    }
}


class Worker2 implements Runnable{
    volatile int threadNo;
    private MkThread2 mkThread;
    private String threadName;

    Worker2(int threadNo, MkThread2 mkThread){
        this.threadNo = threadNo;
        this.mkThread = mkThread;
        this.threadName = "Thread:"+threadNo ;
    }

    public void run(){
        try{
            synchronized (mkThread) {
                while(mkThread.token){
                    while(threadNo != mkThread.nextThreadToRun){
                        mkThread.wait();
                    }
                    if(mkThread.token){//double checking
                        System.out.print(threadName+ "->" + mkThread.arr[mkThread.nextArrayIndex.get()]);
                        if(threadNo == 3) System.out.println();
                        mkThread.nextThreadToRun = getNextThread(threadNo);
                        if(mkThread.nextArrayIndex.get() == mkThread.arr.length-1){
                            mkThread.token = false;
                        }
                        mkThread.nextArrayIndex.incrementAndGet();
                    }
                    mkThread.notifyAll();

                }
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

    private int getNextThread(int threadNo){
        int result = -1;
        switch (threadNo) {
        case (1):
            result = 2;
            break;
        case (2):
            result = 3;
            break;
        case (3):
            result = 1;
            break;
        }
        return result;
    }
}

Upvotes: 0

Way2Go
Way2Go

Reputation: 145

Proper synchronization would help you get the clear answer. I've improved the implementation, you should solve your questions.

    int threadId;
    int moduluos;
    int numOfThreads;

    public ThreadTasks(int id, int nubOfThreads) {
        threadId = id;
        this.numOfThreads = nubOfThreads;
        moduluos = threadId%numOfThreads;
    }

    public void run() {
        print();
    }

    private void print() {
        try {
            while (true) {
                synchronized (monitor) {
                    if (number.get() % numOfThreads != moduluos) {
                        monitor.wait();
                    } else {
                        System.out.println("ThreadId [" + threadId
                                + "] printing -->"
                                + number.getAndIncrement());
                        monitor.notifyAll();
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Upvotes: 0

Siddhartha Sarkar
Siddhartha Sarkar

Reputation: 3

This should work:

package com.sid;

import java.util.concurrent.atomic.AtomicInteger;

public class NumberSequence {

    private AtomicInteger sharedOutput = new AtomicInteger(0);
    private Object object = new Object();

    public static void main(String args[]) {

        NumberSequence t = new NumberSequence();

        ThreadTasks t1 = t.new ThreadTasks(0);
        ThreadTasks t2 = t.new ThreadTasks(1);
        ThreadTasks t3 = t.new ThreadTasks(2);

        Thread ts1 = new Thread(t1);
        Thread ts2 = new Thread(t2);
        Thread ts3 = new Thread(t3);

        ts1.start();
        ts2.start();
        ts3.start();

    }

    private class ThreadTasks implements Runnable {

        private final int threadPosition;

        public ThreadTasks(int threadPosition) {
            super();

            this.threadPosition = threadPosition;
        }

        @Override
        public void run() {

            while (sharedOutput.get() < 10) {

                synchronized (object) {

                    if (sharedOutput.get() % 3 == this.threadPosition) {

                        if(sharedOutput.get() < 10)
                        System.out.println("Printing output for Thread: "
                                + this.threadPosition + "  "
                                + sharedOutput.incrementAndGet());
                    }
                }
            }

        }
    }

}

Upvotes: 0

adeel iqbal
adeel iqbal

Reputation: 494

use wait(), notify(), notifyall() methods of the Java.
you can also take a look at this Tutorial of these methods.

Hope this would be helpful to solve your issue. . .

the output of this example is as under.

Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691715

You should print first, and increment after:

int value = sharedOutput.get() + 1;
System.out.println("Printing output for Thread: "
                        + this.threadPosition + "  "
                        + value);
sharedOutput.incrementAndGet();

That said, all the threads are busy looping, which will lead to 100% CPU usage. You should synchronize the threads instead.

Upvotes: 3

giorashc
giorashc

Reputation: 13713

This is because the time slice for each thread is determined by the OS. So it is possible that thread x increments the shared number but before printing the time slice is passed to the next thread y which now reads the shared number and prints it after incrementing (assuming that thread y got more time than thread x to increament and print the shared number) .

Upvotes: 0

Related Questions