This is a problem I have always heard about in school but never had a reason to mess with until I was asked for an interview.
Prompt: Using 2 threads print "Thread i: The number is 'j'" in order where j = 1:100 and i is the thread number. Thread 1 can only print odd j's and Thread 2 can only print even j's.
EDIT the output of j must be ordered
This was my attempt but I did not move on in the interview process. Is there any fundamental part I am missing? Are there any optimizations?
import java.util.concurrent.Semaphore;
public class ThreadSynchronization implements Runnable {
private int start;
private Semaphore semaphore;
private ThreadSynchronization(int start, Semaphore semaphore) {
this.start = start;
this.semaphore = semaphore;
}
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(1, true);
semaphore.acquireUninterruptibly();
start(1, semaphore);
start(2, semaphore);
semaphore.release();
}
private static void start(int start, Semaphore semaphore) {
ThreadSynchronization ts = new ThreadSynchronization(start, semaphore);
Thread thread = new Thread(ts);
thread.start();
while (thread.getState() != Thread.State.WAITING) ;
}
#Override
public void run() {
for (int i = start; i <= 100; i += 2) {
semaphore.acquireUninterruptibly();
System.out.println("Thread " + start + ": The number is '" + i + "'");
semaphore.release();
}
}
}
One thread can keep aquiring and releasing the Semaphore, while the other thread starves.
You can do this with wait and notify, try this:
import java.util.concurrent.atomic.AtomicInteger;
class Odd implements Runnable {
private AtomicInteger integer;
private final Object lock;
public Odd(AtomicInteger integer, Object lock) {
this.integer = integer;
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
try {
while (integer.get() <= 100) {
while (integer.get() % 2 == 0) {
lock.notify();
lock.wait();
}
if (integer.get() <= 100) {
System.out.println("Thread " +
Thread.currentThread().getName() + ": The number is '" + integer.get() + "'");
}
integer.getAndIncrement();
lock.notify();
}
} catch (Exception e) {
}
}
}
}
class Even implements Runnable {
private AtomicInteger integer;
private final Object lock;
public Even(AtomicInteger integer, Object lock) {
this.integer = integer;
this.lock = lock;
}
#Override
public void run() {
synchronized (lock) {
try {
while (integer.get() <= 100) {
while (integer.get() % 2 != 0) {
lock.notify();
lock.wait();
}
if (integer.get() <= 100) {
System.out.println("Thread " +
Thread.currentThread().getName() + ": The number is '" + integer.get() + "'");
}
integer.getAndIncrement();
lock.notify();
}
} catch (Exception e) {
}
}
}
}
public class ThreadSynchronization {
public static void main(String[] args) throws Exception{
Object lock = new Object();
AtomicInteger integer = new AtomicInteger(1);
Odd odd = new Odd(integer, lock);
Even even = new Even(integer, lock);
Thread thread1 = new Thread(odd, "1");
Thread thread2 = new Thread(even, "2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}
Use an object to arbiter:
public class Switch {
private boolean expected;
public Switch(boolean init) {
expected = init;
}
public void waitFor(boolean value) {
synchronized(this) {
while (value != expected) {
try {
wait();
} catch (InterruptedException ex) {
// deal with it
}
}
expected = !expected;
notifyAll();
}
}
}
Then:
public class ThreadSynchronization implements Runnable {
private static Switch arbiter = new Switch(true);
private int start;
private ThreadSynchronization(int start) {
this.start = start;
}
public static void main(String[] args) {
start(1);
start(2);
}
private static void start(int start) {
ThreadSynchronization ts = new ThreadSynchronization(start);
Thread thread = new Thread(ts);
thread.start();
}
#Override
public void run() {
boolean odd = start%2 != 0;
for (int i = start; i <= 100; i += 2) {
arbiter.waitFor(odd);
System.out.println("Thread " + start + ": The number is '" + i + "'");
}
}
}
You was very close to the right solution, but the task requires 2 semaphores:
public class ThreadSynchronization implements Runnable {
private int start;
private Semaphore semaphore1;
private Semaphore semaphore2;
private ThreadSynchronization(int start, Semaphore semaphore1, Semaphore semaphore2) {
this.start = start;
this.semaphore1 = semaphore1;
this.semaphore2 = semaphore2;
}
private static void start(int start, Semaphore semaphore1, Semaphore semaphore2) {
ThreadSynchronization ts = new ThreadSynchronization(start, semaphore1, semaphore2);
Thread thread = new Thread(ts);
thread.start();
}
#Override
public void run() {
for (int i = start; i <= 100; i += 2) {
semaphore1.acquireUninterruptibly();
System.out.println("Thread " + start + ": The number is '" + i + "'");
semaphore2.release();
}
}
public static void main(String[] args) {
Semaphore semaphore1 = new Semaphore(1);
Semaphore semaphore2 = new Semaphore(0);
start(1, semaphore1, semaphore2);
start(2, semaphore2, semaphore1); // in reverse order
}
}
For this simple task it is enough to use AutomicInteger:
public static class CounterTask implements Runnable {
private final int id;
private final AtomicInteger counter;
private final int max;
private final IntPredicate predicate;
public CounterTask(int id, AtomicInteger counter, int max, IntPredicate predicate) {
this.id = id;
this.counter = counter;
this.max = max;
this.predicate = predicate;
}
#Override
public void run() {
while (counter.get() <= max) {
if (predicate.test(counter.get())) {
System.out.format("Thread %d: The number is '%d'\n", id, counter.get());
counter.incrementAndGet();
}
}
}
}
public static void main(String... args) throws InterruptedException {
final int max = 100;
final AtomicInteger counter = new AtomicInteger();
Thread oddThread = new Thread(new CounterTask(1, counter, max, val -> val % 2 == 0));
Thread evenThread = new Thread(new CounterTask(2, counter, max, val -> val % 2 != 0));
oddThread.start();
evenThread.start();
oddThread.join();
evenThread.join();
}
While wait and notify can do the job, I think the use of Semaphore can make for more readable code. The code below focusses on a solution for threads "talking" to each other and synchornizing where needed: I imagine in a real use case 2 threads do important work and at some point need to synchronize and determine who goes first.
import java.util.concurrent.Semaphore;
public class LockStep {
public static void main(String[] args) {
Semaphore evenTurn = new Semaphore(1);
Semaphore oddTurn = new Semaphore(0);
int max = 50;
Thread even = new Thread(new Worker(evenTurn, oddTurn, max));
even.start();
Thread odd = new Thread(new Worker(oddTurn, evenTurn, max));
odd.start();
try {
even.join();
odd.join();
} catch (Exception e) {
System.out.println("No join for me: " + e);
}
System.out.println("Finished");
}
static class Worker implements Runnable {
final Semaphore myTurn;
final Semaphore theirTurn;
final int maxTurns;
public Worker(Semaphore myTurn, Semaphore theirTurn, int maxTurns) {
this.myTurn = myTurn;
this.theirTurn = theirTurn;
this.maxTurns = maxTurns;
}
#Override
public void run() {
int turn = 0;
while (turn < maxTurns) {
try {
myTurn.acquire();
turn += 1;
System.out.println(Thread.currentThread().getName() + " " + turn);
theirTurn.release();
} catch (Exception e) {
System.out.println("Oops: " + e);
}
}
}
}
}
I am trying to write a simple code to print numbers in sequence. Scenario is like
Thread Number
T1 1
T2 2
T3 3
T1 4
T2 5
T3 6
T1 7
T2 8
T3 9
...and so on.
Here is the
public class ThreadNumberPrinter {
Object monitor = new Object();
AtomicInteger number = new AtomicInteger(1);
public static void main(String[] args) {
ThreadNumberPrinter tnp = new ThreadNumberPrinter();
Thread t1 = new Thread(tnp.new Printer(1, 3));
Thread t2 = new Thread(tnp.new Printer(2, 3));
Thread t3 = new Thread(tnp.new Printer(3, 3));
t3.start();
t1.start();
t2.start();
}
class Printer implements Runnable {
int threadId;
int numOfThreads;
public Printer(int id, int nubOfThreads) {
threadId = id;
this.numOfThreads = nubOfThreads;
}
public void run() {
print();
}
private void print() {
try {
while (true) {
Thread.sleep(1000l);
synchronized (monitor) {
if (number.get() % numOfThreads != threadId) {
monitor.wait();
} else {
System.out.println("ThreadId [" + threadId
+ "] printing -->"
+ number.getAndIncrement());
monitor.notifyAll();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
But just after 2nd thread runs and prints the number 2, all thread get into wait stage and nothing gets printed. I am not sure where I am doing wrong.
Any help would be greatly appreciated.
public class TestClass {
private volatile Integer count = 1;
private volatile Integer threadIdToRun = 1;
private Object object = new Object();
public static void main(String[] args) {
TestClass testClass = new TestClass();
Thread t1 = new Thread(testClass.new Printer(1));
Thread t2 = new Thread(testClass.new Printer(2));
Thread t3 = new Thread(testClass.new Printer(3));
t1.start();
t2.start();
t3.start();
}
class Printer implements Runnable {
private int threadId;
public Printer(int threadId) {
super();
this.threadId = threadId;
}
#Override
public void run() {
try {
while (count <= 20) {
synchronized (object) {
if (threadId != threadIdToRun) {
object.wait();
} else {
System.out.println("Thread " + threadId + " printed " + count);
count += 1;
if (threadId == 1)
threadIdToRun = 2;
else if (threadId == 2)
threadIdToRun = 3;
else if (threadId == 3)
threadIdToRun = 1;
object.notifyAll();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Above program gives output
Thread 1 printed 1
Thread 2 printed 2
Thread 3 printed 3
Thread 1 printed 4
Thread 2 printed 5
Thread 3 printed 6
Thread 1 printed 7
Thread 2 printed 8
Thread 3 printed 9
Thread 1 printed 10
Thread 2 printed 11
Thread 3 printed 12
Thread 1 printed 13
Thread 2 printed 14
Thread 3 printed 15
Thread 1 printed 16
Thread 2 printed 17
Thread 3 printed 18
Thread 1 printed 19
Thread 2 printed 20
Well, the problem is that modulo 3 % 3 is 0. Change your threadIds to 0..2 instead of 1..3 and hopefully it should work.
Though this is a bad way for using threads, if we still want it a generic solution can be to have a worker thread which will store its id:
class Worker extends Thread {
private final ResourceLock resourceLock;
private final int threadNumber;
private final AtomicInteger counter;
private volatile boolean running = true;
public Worker(ResourceLock resourceLock, int threadNumber, AtomicInteger counter) {
this.resourceLock = resourceLock;
this.threadNumber = threadNumber;
this.counter = counter;
}
#Override
public void run() {
while (running) {
try {
synchronized (resourceLock) {
while (resourceLock.flag != threadNumber) {
resourceLock.wait();
}
System.out.println("Thread:" + threadNumber + " value: " + counter.incrementAndGet());
Thread.sleep(1000);
resourceLock.flag = (threadNumber + 1) % resourceLock.threadsCount;
resourceLock.notifyAll();
}
} catch (Exception e) {
System.out.println("Exception: " + e);
}
}
}
public void shutdown() {
running = false;
}
}
The ResourceLock class would store flag and max threads count:
class ResourceLock {
public volatile int flag;
public final int threadsCount;
public ResourceLock(int threadsCount) {
this.flag = 0;
this.threadsCount = threadsCount;
}
}
And then main class can use it as below:
public static void main(String[] args) throws InterruptedException {
final int threadsCount = 3;
final ResourceLock lock = new ResourceLock(threadsCount);
Worker[] threads = new Worker[threadsCount];
final AtomicInteger counter = new AtomicInteger(0);
for(int i=0; i<threadsCount; i++) {
threads[i] = new Worker(lock, i, counter);
threads[i].start();
}
Thread.sleep(10000);
System.out.println("Will try to shutdown now...");
for(Worker worker: threads) {
worker.shutdown();
}
}
Here after a certain delay we may like to stop the count and the method shutdown in worker provides this provision.
Below code uses the logic of notifying the next thread to print the number and then incrementing it by 1 and then again notifying the next thread and then go in wait state till some thread notifies it.
Eg. T1 first prints the value and then makes boolean "second" true for T2 to print the next number. T2 after printing the number makes boolean "third" true for T3. T3 does the same thing by making boolean "first" true for T1 to print the next number.
T1 -> T2 -> T3 -> T1 -> T2 -> T3 -> ........ and so on.
public class Test{
public static volatile int i = 0;
public static void main(String[] args) throws InterruptedException {
Object monitor = new Object();
Notifier notifier = new Notifier(monitor);
Thread thread1 = new Thread(notifier, "T1");
Thread thread2 = new Thread(notifier, "T2");
Thread thread3 = new Thread(notifier, "T3");
thread1.start();
thread2.start();
thread3.start();
}
}
class Notifier implements Runnable {
private Object monitor = null;
private static int i = 1;
private static boolean first = true;
private static boolean second = false;
private static boolean third = false;
public Notifier(Object objcurr) {
this.monitor = objcurr;
}
#Override
public void run() {
try {
while (true) {
synchronized (monitor) {
String Tname = Thread.currentThread().getName();
if (first && Tname.equalsIgnoreCase("T1")) {
print();
first = false;
second = true;
monitor.notifyAll();
monitor.wait();
} else if (second && Tname.equalsIgnoreCase("T2")) {
print();
second = false;
third = true;
monitor.notifyAll();
monitor.wait();
} else if (third && Tname.equalsIgnoreCase("T3")) {
print();
third = false;
first = true;
monitor.notifyAll();
monitor.wait();
} else {
monitor.wait();
}
}
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void print() {
System.out.println(Thread.currentThread().getName() + " - " + Notifier.i++);
}
How about this?
public class PrintNumbers implements Runnable {
public static final int NO_OF_THREADS = 3;
public static final int MAX_DIGIT = 20;
public static final String THREAD_NAME_PREFIX = "t";
volatile int current = 1;
private Object lock = new Object();
public static void main(String[] args) {
PrintNumbers printNumbers = new PrintNumbers();
for (int i = 1; i <= NO_OF_THREADS; i++) {
new Thread(printNumbers, THREAD_NAME_PREFIX + i).start();
}
}
#Override
public void run() {
String printThread;
while (current < MAX_DIGIT) {
synchronized (lock) {
if (current % NO_OF_THREADS != 0) {
printThread = THREAD_NAME_PREFIX + current % NO_OF_THREADS;
} else {
printThread = THREAD_NAME_PREFIX + NO_OF_THREADS;
}
if (!printThread.equals(Thread.currentThread().getName())) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (printThread.equals(Thread.currentThread().getName())) {
System.out.println(String.format("Thread %s : %s", Thread.currentThread().getName(), current));
current = current + 1;
}
lock.notifyAll();
}
}
}
}
package com.sourav.mock.Thread;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreeThreadComunication implements Runnable {
AtomicInteger counter;
int[] array;
static final Object mutex = new Object();
public ThreeThreadComunication(int[] array, AtomicInteger counter){
this.counter = counter;
this.array = array;
}
#Override
public void run() {
int i = 0;
while(i < array.length){
synchronized(mutex){
if(Integer.parseInt(Thread.currentThread().getName()) == counter.get()){
System.out.println(array[i]);
if(counter.get() == 3){
counter.getAndSet(1);
}else{
int c = counter.get();
counter.getAndSet(++c);
}
i++;
}
mutex.notifyAll();
try {
mutex.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package com.sourav.mock.Thread;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreeThreadComunicationTest {
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(1);
int[] array1 = new int[]{1, 4, 7};
int[] array2 = new int[]{2, 5, 8};
int[] array3 = new int[]{3, 6, 9};
ThreeThreadComunication obj1 = new ThreeThreadComunication(array1, counter);
ThreeThreadComunication obj2 = new ThreeThreadComunication(array2, counter);
ThreeThreadComunication obj3 = new ThreeThreadComunication(array3, counter);
Thread t1 = new Thread(obj1, "1");
Thread t2 = new Thread(obj2, "2");
Thread t3 = new Thread(obj3, "3");
t1.start();
t2.start();
t3.start();
}
}
public class EvenOdd1 {
//public static String str ="str1";
public static void main(String[] args) {
// TODO Auto-generated method stub
EvenOdd1 edd1 = new EvenOdd1();
AbThread tr2 = new AbThread(0,edd1);
AbThread tr3 = new AbThread(1,edd1);
AbThread tr4 = new AbThread(2,edd1);
tr2.start();
tr3.start();
tr4.start();
}
}
class AbThread extends Thread {
int mod;
int mod_count=1;
EvenOdd1 edd1;
public static int count=1;
int num_thread=3;
public AbThread(int mod,EvenOdd1 edd1){
this.mod = mod;
this.edd1 = edd1;
}
public void run()
{
synchronized(edd1)
{
try{
while(true){
while(count%num_thread!=mod)
edd1.wait();
if(count==30)
break;
print();
edd1.wait();
}
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void print()
{
int val = mod==1?2*mod_count:(mod==2?3*mod_count:4*mod_count);
System.out.println(Thread.currentThread().getName() + " : " + val);
edd1.notifyAll();
count=count+1;
this.mod_count++ ;
}
}
public class PrintThreadsSequentially {
static int number = 1;
static final int PRINT_NUMBERS_UPTO = 20;
static Object lock = new Object();
static class SequentialThread extends Thread {
int remainder = 0;
int noOfThreads = 0;
public SequentialThread(String name, int remainder, int noOfThreads) {
super(name);
this.remainder = remainder;
this.noOfThreads = noOfThreads;
}
#Override
public void run() {
while (number < PRINT_NUMBERS_UPTO) {
synchronized (lock) {
while (number % noOfThreads != remainder) { // wait for numbers other than remainder
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + " value " + number);
number++;
lock.notifyAll();
}
}
}
}
public static void main(String[] args) {
SequentialThread first = new SequentialThread("First Thread", 0, 4);
SequentialThread second = new SequentialThread("Second Thread", 1, 4);
SequentialThread third = new SequentialThread("Third Thread", 2, 4);
SequentialThread fourth = new SequentialThread("Fourth Thread", 3, 4);
first.start(); second.start(); third.start(); fourth.start();
}
}
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();
}
}
}
I have tried it below simple way to print in sequence using three threads and it is working well.
public class AppPrint123 {
static int count = 1;
static int counter = 1;
static Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (lock) {
try {
Thread.sleep(100);
while (count != 1) {
lock.wait();
}
System.out.println(Thread.currentThread().getName() + ": " + counter);
count++;
counter++;
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notifyAll();
}
}
}
}, "T1");
Thread t2 = new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (lock) {
try {
Thread.sleep(100);
while (count != 2) {
lock.wait();
}
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter++;
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notifyAll();
}
}
}
}, "T2");
Thread t3 = new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (lock) {
try {
Thread.sleep(100);
while (count != 3) {
lock.wait();
}
System.out.println(Thread.currentThread().getName() + ": " + counter);
count = count - 2;
counter++;
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notifyAll();
}
}
}
}, "T3");
t1.start();
t2.start();
t3.start();
}
}
You can print count variable instead if you want to generate output like 123123123 in sequence using three threads.
Bad way to do but ask is to implement using multiple threads:
private static AtomicInteger currentThreadNo = new AtomicInteger(0);
private static int currentNo = 1;
private static final Object lock = new Object();
Above, these values are static so that they remain same for all the worker objects.
import java.util.concurrent.atomic.AtomicInteger;
public class PrintNumbersUsingNThreads implements Runnable {
private final int threadNo;
private final int totalThreads;
private static AtomicInteger currentThreadNo = new AtomicInteger(0);
private static int currentNo = 1;
private static final Object lock = new Object();
public PrintNumbersUsingNThreads(int threadNo, int totalThreads) {
this.threadNo = threadNo;
this.totalThreads = totalThreads;
}
#Override
public void run() {
while (true) {
while (currentThreadNo.get() % totalThreads != threadNo) {
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " printing " + currentNo);
currentNo++;
int curr = currentThreadNo.get();
if (curr == totalThreads) {
currentThreadNo.set(1);
} else {
currentThreadNo.incrementAndGet();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
lock.notifyAll();
}
}
}
public static void main(String[] args) {
int totalThreads = 3;
for(int i = 0; i < totalThreads; i++){
new Thread(new PrintNumbersUsingNThreads(i,totalThreads),"thread"+i).start();
}
}
}
output:
thread0 printing 1
thread1 printing 2
thread2 printing 3
thread0 printing 4
thread1 printing 5
thread2 printing 6
thread0 printing 7
thread1 printing 8
thread2 printing 9
thread0 printing 10
thread1 printing 11
thread2 printing 12
thread0 printing 13
thread1 printing 14
thread2 printing 15
thread0 printing 16
thread1 printing 17
thread2 printing 18
Below is very generic code. i agree it is not good practice to use multiple threads for such cases
class MultipleThreads implements Runnable {
AtomicInteger integer;
int max_val = 100;
int remainder;
int numofThreads;
public MultipleThreads(AtomicInteger integer, int remainder, int numofThreads) {
this.integer = integer;
this.remainder = remainder;
this.numofThreads = numofThreads;
}
#Override
public void run() {
while (integer.intValue() <= max_val) {
synchronized (integer) {
while (integer.intValue() % numofThreads != remainder) {
try {
integer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (integer.intValue() > max_val)
break;
System.out.println("printing :" + Thread.currentThread().getName() + " : " + integer.getAndIncrement());
integer.notifyAll();
}
}
}
}
public class ThreadSynchronization {
public static void main(String[] args) {
AtomicInteger at = new AtomicInteger(1);
MultipleThreads th1 = new MultipleThreads(at, 1, 5);
MultipleThreads th2 = new MultipleThreads(at, 2, 5);
MultipleThreads th3 = new MultipleThreads(at, 3, 5);
MultipleThreads th4 = new MultipleThreads(at, 4, 5);
MultipleThreads th5 = new MultipleThreads(at, 0, 5);
new Thread(th1).start();
new Thread(th2).start();
new Thread(th3).start();
new Thread(th4).start();
new Thread(th5).start();
}
}
Also, make sure to use pthread_cond_broadcast instead of phread_cond_signal
#include "stdio.h"
#include "stdlib.h"
#include "pthread.h"
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
void *functionCount1();
void *functionCount2();
void *functionCount3();
int count = 0;
#define COUNT_DONE 10
void main()
{
pthread_t thread1, thread2, thread3;
pthread_create( &thread1, NULL, &functionCount1, NULL);
pthread_create( &thread2, NULL, &functionCount2, NULL);
pthread_create( &thread3, NULL, &functionCount3, NULL);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
pthread_join( thread3, NULL);
exit(0);
}
// Let me write what I think
// we can;t do he %2 %3 since multiple threads may satisfy the conditions.
// count = 0; count % 3 = 0
// count = 1; count % 3 = 1
// count = 2; count % 3 = 2
// count = 3; cooun % 3 = 0
// Print odd numbers
void *functionCount1()
{
for(;;) {
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );
if ( count % 3 == 0 ) {
printf("Counter value functionCount1: %d\n",count);
count++;
pthread_cond_broadcast( &condition_var );
} else {
pthread_cond_wait( &condition_var, &count_mutex );
}
if ( count >= COUNT_DONE ) {
pthread_mutex_unlock( &count_mutex );
return(NULL);
}
pthread_mutex_unlock( &count_mutex );
}
}
// print even numbers
void *functionCount2()
{
for(;;) {
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );
if ( count % 3 == 1 ) {
printf("Counter value functionCount2: %d\n",count);
count++;
pthread_cond_broadcast( &condition_var );
} else {
pthread_cond_wait( &condition_var, &count_mutex );
}
if( count >= COUNT_DONE ) {
pthread_mutex_unlock( &count_mutex );
return(NULL);
}
pthread_mutex_unlock( &count_mutex );
}
}
// print even numbers
void *functionCount3()
{
for(;;) {
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );
if ( count % 3 == 2 ) {
printf("Counter value functionCount3: %d\n",count);
count++;
pthread_cond_broadcast( &condition_var );
} else {
pthread_cond_wait( &condition_var, &count_mutex );
}
if( count >= COUNT_DONE ) {
pthread_mutex_unlock( &count_mutex );
return(NULL);
}
pthread_mutex_unlock( &count_mutex );
}
}
Here is my solution. It is pretty simple and easy to understand. It will help if you are using static variables...
Note that using a lock object is crucial as I tried initially with the this keyword(ex: synchronized(this) ), but it was not been synchronized among all threads.
public class Assignment_Three_Threads {
public static int TotalNumberOfThreads = 3;
public static void main(String[] args) {
multiThread t1 = new multiThread(1);
multiThread t2 = new multiThread(2);
multiThread t3 = new multiThread(3);
t1.start();
t2.start();
t3.start();
}
}
class multiThread extends Thread{
int k=2;
private int threadId ;
private static int threadIdToRun = 1;
private static final Object lock = new Object();
multiThread(int id)
{
super();
this.threadId = id;
}
#Override
public void run() {
for (int i = 0; i < k; i++) {
synchronized (lock) {
while(true) {
if (this.threadId != threadIdToRun) {
try {
lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (this.threadId == threadIdToRun) {
System.out.println("Thread : " + this.threadId);
threadIdToRun =
(threadIdToRun % Assignment_Three_Threads.TotalNumberOfThreads) + 1;
// System.out.println("Next Thread to be printed " + threadIdToRun);
lock.notifyAll();
break;
}
}
}
}
}
}
A general solution for any number of Threads-
for 3 thread logic =MIN % 3 != reminder
for 4 thread= MIN % 4 != reminder
public class PrintSequenceRunnable1 implements Runnable {
int reminder;
static Object lock=new Object();
static int MIN=1;
int MAX=20;
PrintSequenceRunnable1(int reminder){
this.reminder=reminder;
}
public static void main(String[] args) {
Thread t1= new Thread(new PrintSequenceRunnable1(1),"T1");
Thread t2= new Thread(new PrintSequenceRunnable1(2),"T2");
Thread t3= new Thread(new PrintSequenceRunnable1(0),"T3");
t1.start();
t2.start();
t3.start();
}
#Override
public void run() {
synchronized (lock) {
while (MIN < MAX - 1) {
while (MIN % 3 != reminder) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "-" + MIN);
MIN++;
lock.notifyAll();
}
}
}
}
public class ThreadTask implements Runnable {
private int counter;
private int threadID;
private final Object lock;
private int prev;
public ThreadTask(Object obj, int threadid, int counter){
this.lock = obj; // monitor
this.threadID = threadid; //id of thread
this.counter = counter;
this.prev =threadid + 1;
}
public void run(){
while(counter<100){
synchronized(lock){
if(counter == this.prev && this.threadID % 3 == this.threadID){
System.out.println("T" + this.threadID + " = " + this.prev);
this.prev = this.prev + 3;
}
counter++;
lock.notifyAll();
try{
lock.wait();
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
public class ThreadMain {
static volatile int counter = 1;
public static void main(String args[]) throws InterruptedException{
final Object lock = new Object();
ThreadTask first = new ThreadTask(lock, 0, counter);
ThreadTask second = new ThreadTask(lock, 1, counter);
ThreadTask third = new ThreadTask(lock, 2, counter);
Thread t1 = new Thread(first, "first");
Thread t2 = new Thread(second, "second");
Thread t3 = new Thread(third, "third");
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
}
package ThreadCoreConcepts;
import java.util.ArrayList;
import java.util.List;
/**
* 3 Thread T1,T2,T3 will print output {1,2,3 4,5,6 7,8,9} Where T1 will print
* {1,4,7} , T2 will print { 2,5,8} and T3 will print {3,6,9}
*
* #author harsmahe
*
*/
public class ThreeThreadSequenceGen {
private volatile static int value = 1;
public static void main(String args[]) throws InterruptedException {
ThreeThreadSequenceGen gen = new ThreeThreadSequenceGen();
Object mutex = new Object();
Thread t1 = new Thread(gen.new RunThread(1, mutex));
t1.setName("1");
Thread t2 = new Thread(gen.new RunThread(2, mutex));
t2.setName("2");
Thread t3 = new Thread(gen.new RunThread(3, mutex));
t3.setName("3");
t1.start();
t2.start();
t3.start();
}
class RunThread implements Runnable {
private int start = 0;
private Object mutex;
private List<Integer> list = new ArrayList<Integer>();
public RunThread(final int start, Object mutex) {
// TODO Auto-generated constructor stub
this.start = start;
this.mutex = mutex;
}
#Override
public void run() {
try {
while (value <= 9) {
// while (true) {
// TODO Auto-generated method stub
int name = Integer.valueOf(Thread.currentThread().getName());
// System.out.println("[" + Thread.currentThread().getName()
// + "]");
// notifyAll();
synchronized (mutex) {
if (name == 1 && value == start) {
list.add(value);
System.out.println("[" + Thread.currentThread().getName() + "]" + value);
start = start + 3;
value++;
mutex.notifyAll();
mutex.wait();
} else if (name == 2 && value == start) {
System.out.println("[" + Thread.currentThread().getName() + "]" + value);
list.add(value);
start = start + 3;
value++;
mutex.notifyAll();
mutex.wait();
} else if (name == 3 && value == start) {
System.out.println("[" + Thread.currentThread().getName() + "]" + value);
list.add(value);
start = start + 3;
value++;
mutex.notifyAll();
if (value < 9) {
mutex.wait();
}
} else {
mutex.notifyAll();
// mutex.wait();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// System.out.println(list);
}
}
}
}
I want to print a series of 1 to 100 number using n number of threads (lets take 10 threads for this). Condition is 1st thread will have a sequence number from 1, 11,21....91, 2nd thread will have a sequence 2,12,22.....92 and so on. All other threads will have a sequence number like that. Now I want to print number in sequence 1 to 100. I know we can use synchronization, wait and notify method and using a variable or flag counter but I don't think this is a good idea to use it. I want to use without concurrency (like executors etc) how will I do that. Please suggest.
public class PrintNumberSequenceUsingRunnable {
int notifyValue = 1;
public static void main(String[] args) {
PrintNumberSequenceUsingRunnable sequence = new PrintNumberSequenceUsingRunnable();
Thread f = new Thread(new First(sequence), "Fisrt");
Thread s = new Thread(new Second(sequence), "Second");
Thread t = new Thread(new Third(sequence), "Third");
f.start();
s.start();
t.start();
}
}
class First implements Runnable {
PrintNumberSequenceUsingRunnable sequence;
public First(PrintNumberSequenceUsingRunnable sequence) {
this.sequence = sequence;
}
#Override
public void run() {
printFist();
}
private void printFist() {
synchronized (sequence) {
for (int i = 1; i <= 20; i += 3) {
while (sequence.notifyValue != 1) {
try {
sequence.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i);
sequence.notifyValue = 2;
sequence.notifyAll();
}
}
}
}
class Second implements Runnable {
PrintNumberSequenceUsingRunnable sequence;
public Second(PrintNumberSequenceUsingRunnable sequence) {
this.sequence = sequence;
}
#Override
public void run() {
printSecond();
}
private void printSecond() {
synchronized (sequence) {
for (int i = 2; i <= 20; i += 3) {
while (sequence.notifyValue != 2) {
try {
sequence.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i);
sequence.notifyValue = 3;
sequence.notifyAll();
}
}
}
}
class Third implements Runnable {
PrintNumberSequenceUsingRunnable sequence;
public Third(PrintNumberSequenceUsingRunnable sequence) {
this.sequence = sequence;
}
#Override
public void run() {
printThrid();
}
private void printThrid() {
synchronized (sequence) {
for (int i = 3; i <= 20; i += 3) {
while (sequence.notifyValue != 3) {
try {
sequence.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " " + i);
sequence.notifyValue = 1;
sequence.notifyAll();
}
}
}
}
You need to have values sorted on each threads. Each time a thread writes a number, it triggers an event in an event bus. All threads are subscribed to the event.
You start the system by triggering the event [minimum value - 1].
Each thread will receive a notification that the value [minimum value - 1] has been published. Only the thread that has the value [minimum value] will act and will trigger a new event for value [minimum value + 1].
Edit: I haven't tested it, but something like this.
static void main(String[] args) {
List<Deque<Integer>> publishQueues = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
new Thread(new Worker(i, publishQueues)).start();
}
}
class Worker implements Runnable {
Deque subscriberQueue;
List<Deque<Integer>> publishQueues;
int i;
Worker(int i, List<Deque<Integer>> publishQueues) {
this.i = i;
this.publishQueues = publishQueues;
this.subscriberQueue = new ConcurrentLinkedDeque<>();
this.publishQueues.add(this.subscriberQueue);
}
void Run() {
LinkedList<Integer> ints = new LinkedList<>();
for (int j = i; j <= 100; j+=10) {
ints.add(j);
}
while (true) {
Integer publishedInteger = subscriberQueue.poll();
if (publishedInteger == ints.getFirst() - 1) {
Integer integer = ints.poll();
System.out.println(integer);
for (Dequeu<Integer> publishQueue : publishQueues) {
publishQueue.addLast(integer);
}
}
}
}
}