1

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

        }
    }

}
Lokesh
  • 7,810
  • 6
  • 48
  • 78

15 Answers15

3

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Perfect. Works well for me. – Lokesh Mar 10 '13 at 14:01
  • How is using incrementAndGet() in sysout directly different? – sgp15 Mar 10 '13 at 14:15
  • In the original code, `incrementAndGet()` is called. Then the returned value is concatenated with the rest of the output message. Then only the message is printed. So there is a long time between the increment and the printing of the message where another thread sees the new value of the AtomicInteger. – JB Nizet Mar 10 '13 at 14:19
  • For a moment I thought so too. But isn't incrementAndGet() atomic? – sgp15 Mar 10 '13 at 14:22
  • 1
    Yes, it's atomic, so what? It's still executed before the print is executed. So other threads see the new value, and can print their line before the first thread. – JB Nizet Mar 10 '13 at 15:35
2

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);
       }
     }
Gopinath
  • 49
  • 2
0

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) .

giorashc
  • 13,691
  • 3
  • 35
  • 71
0

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

adeel iqbal
  • 494
  • 5
  • 23
  • i already stated i dont want to use synchronize!! so no lock means wait notify are out of picture. – Lokesh Mar 10 '13 at 13:53
0

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

        }
    }

}
abarisone
  • 3,707
  • 11
  • 35
  • 54
  • 1
    Could you please elaborate more your answer adding a little more description about the solution you provide? – abarisone Jun 11 '15 at 08:53
0

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

}
Way2Go
  • 135
  • 1
  • 1
  • 7
0
    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;
    }
}
ManishKr
  • 211
  • 2
  • 9
0
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();
    }
}


}
0

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.

Drona
  • 6,886
  • 1
  • 29
  • 35
0
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();
  }

}
αƞjiβ
  • 3,056
  • 14
  • 58
  • 95
arora
  • 11
  • 3
0

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

            }
        }
    }

}
Nitin
  • 21
  • 2
0

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.

0

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();
        }
    }
}
Pang
  • 9,564
  • 146
  • 81
  • 122
s-radix
  • 21
  • 3
0
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);
        }
     }
    }
}
Kumar Ashutosh
  • 1,121
  • 10
  • 33
0
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

AS Mackay
  • 2,831
  • 9
  • 19
  • 25