Let's say I want to have n threads running and I want to output something when ALL threads complete. Here are the methods I've tried:
//This uses a ThreadGroup called tGroup
while(tGroup.activeCount() > 0) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This next is just with a while loop and an ArrayList storing Threads
boolean alive = true;
int count = 0;
while (alive) {
count = 0;
for (int i = 0; i < numThreads; i++) {
if (!threads.get(i).isAlive()) {
count++;
}
if (count == numThreads) {
alive = false;
break;
}
}
}
Loop through all your threads and join() each one. The join() will block on any unfinished thread until it finishes.
I think what you want to use is a CountDownLatch as this was built specifically for just this type of situation. Each worker thread will notify the latch when it is complete, and then any threads that have called await() on the latch will hold operation until the count down is complete. Please look at the sample code in the API link I've given above to see how easy and flexible this is to use.
Edit:
Oops, I guess I was too late in posting this. But regardless that you accepted the other answer, you still owe it to yourself to check this out as it is quite elegant and easy to use.
For example:
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchEg {
public static void main(String[] args) {
int threadCount = 8;
CountDownLatch latch = new CountDownLatch(threadCount);
System.out.println("Start all threads");
for (int i = 0; i < threadCount; i++) {
new Thread(new MyRunnable(latch, i)).start();
}
System.out.println("All threads started");
try {
latch.await();
} catch (InterruptedException e) {}
System.out.println("All threads finished");
}
}
class MyRunnable implements Runnable {
private CountDownLatch latch;
private Random rand = new Random();
private long delay;
private int id;
public MyRunnable(CountDownLatch latch, int id) {
this.latch = latch;
delay = (rand.nextInt(4) + 1) * 1000;
this.id = id;
}
#Override
public void run() {
System.out.println("Start thread: " + id);
try {
Thread.sleep(delay);
} catch (InterruptedException e) {}
System.out.println("End thread: " + id);
latch.countDown();
}
}
Don't you mean this:
boolean alive = true;
int count = 0;
while (alive) {
count = 0;
for (int i = 0; i < numThreads; i++) {
if (!threads.get(i).isAlive()) {
count++;
}
}
if (count == numThreads) {
alive = false;
}
}
?
Related
In this code I'm using 10 threads updating an AtomicInteger variable. I expect the final result of Counter.getInstance().holder.n to be 1000000, but it prints out random number like 991591.
What's wrong with my code?
public class Test {
public static void main(String[] args) {
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
list.add(new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
Counter.getInstance().holder.n.incrementAndGet();
}
}
});
}
for (Thread thread : list) {
thread.start();
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Counter.getInstance().holder.n);
}
}
class Counter {
private static Counter counter;
Holder holder = new Holder();
public static Counter getInstance() {
if (counter == null) {
counter = new Counter();
}
return counter;
}
class Holder {
AtomicInteger n = new AtomicInteger(0);
}
}
You have two major concurrent issues here:
You don't wait for every Thread to finish work correctly. There are multiple ways to achieve that, the simplest is to use Thread.join().
Your singleton implementation doesn't seem correct. I suppose you intended to implement it with an inner class. It seems that this answer can help to understand what's happening here.
Here is the implementation that seems more or less correct.
class Test {
public static void main(String[] args) throws InterruptedException {
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
list.add(new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
Counter.getInstance().n.incrementAndGet();
}
}
});
}
for (Thread thread : list) {
thread.start();
}
for (Thread thread : list) {
thread.join();
}
System.out.println(Counter.getInstance().n);
}
}
class Counter {
public AtomicInteger n = new AtomicInteger(0);
public static Counter getInstance() {
return Holder.instance;
}
private static class Holder {
private static final Counter instance = new Counter();
}
}
You can use something like CountDownLatch as well. For example:
final int count = 10;
CountDownLatch latch = new CountDownLatch(count);
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < count; i++) {
list.add(new Thread() {
public void run() {
for (int i = 0; i < 100000; i++) {
Counter.getInstance().n.incrementAndGet();
}
latch.countDown();
}
});
}
for (Thread thread : list) {
thread.start();
}
latch.await();
System.out.println(Counter.getInstance().n);
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 out the Producer-Consumer problem using Semaphore. The program looks fine to me except for one place.
public class ProducerConsumerWithSemaphores
{
private final ArrayList<Integer> list = new ArrayList<>(5);
private final Semaphore semaphoreProducer = new Semaphore(1);
private final Semaphore semaphoreConsumer = new Semaphore(0);
private void produce() throws InterruptedException
{
for(int i = 0;i< 5;i++)
{
semaphoreProducer.acquire();
list.add(i);
System.out.println("Produced: " + i);
semaphoreConsumer.release();
}
}
private void consumer() throws InterruptedException
{
while (!list.isEmpty()) /// This line is where I have the doubt
{
semaphoreConsumer.acquire();
System.out.println("Consumer: " + list.remove(list.size()-1));
semaphoreProducer.release();
Thread.sleep(100);
}
}
public static void main(String[] args)
{
final ProducerConsumerWithSemaphores obj = new ProducerConsumerWithSemaphores();
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
obj.produce();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
obj.consumer();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}).start();
}
}
Is it okay to check the list if it is not empty before acquiring the semaphore? Will this cause any problem in multithreaded environment?
private void consumer() throws InterruptedException
{
while (!list.isEmpty()) /// This line is where I have the doubt
The problem is, if consumer runs faster than producer, your consumer quit immediately, then you have no consumer!!
The correct example looks like,
Producer–consumer problem#Using semaphores. I believe your intention is not to use true as endless loop because you want Producer/Consumer to quit when job is done. If that's your intention, you can 1. set a totalCount to end the loop. 2. Or a boolean flag which will be set by producer after putItemIntoBuffer when producer put the last one. The flag must be protected as well as the buffer.(update: this method doesn't work if there's multiple producers/consumers) 3. Simulate EOF ( idea taken from producer - consume; how does the consumer stop?)
Will this cause any problem in multithreaded environment?
Your critical section (your list) is not protected . Usually we use 3 semaphores. The 3rd one is used as a mutex to protect the buffer.
To stop producers/consumers,
Example code with method 1:
public class Test3 {
private Semaphore mutex = new Semaphore(1);
private Semaphore fillCount = new Semaphore(0);
private Semaphore emptyCount = new Semaphore(3);
private final List<Integer> list = new ArrayList<>();
class Producer implements Runnable {
private final int totalTasks;
Producer(int totalTasks) {
this.totalTasks = totalTasks;
}
#Override
public void run() {
try {
for (int i = 0; i < totalTasks; i++) {
emptyCount.acquire();
mutex.acquire();
list.add(i);
System.out.println("Produced: " + i);
mutex.release();
fillCount.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private final int totalTasks;
Consumer(int totalTasks) {
this.totalTasks = totalTasks;
}
#Override
public void run() {
try {
for (int i = 0; i < totalTasks; i++) {
fillCount.acquire();
mutex.acquire();
int item = list.remove(list.size() - 1);
System.out.println("Consumed: " + item);
mutex.release();
emptyCount.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void runTest() {
int numProducer = 3;
int tasksPerProducer = 10;
int numConsumer = 6;
int tasksPerConsumer = 5;
for (int i = 0; i < numProducer; i++) {
new Thread(new Producer(tasksPerProducer)).start();
}
for (int i = 0; i < numConsumer; i++) {
new Thread(new Consumer(tasksPerConsumer)).start();
}
}
public static void main(String[] args) throws IOException {
Test3 t = new Test3();
t.runTest();
}
}
Example code with method 3:
public class Test4 {
private Semaphore mutex = new Semaphore(1);
private Semaphore fillCount = new Semaphore(0);
private Semaphore emptyCount = new Semaphore(3);
private Integer EOF = Integer.MAX_VALUE;
private final Queue<Integer> list = new LinkedList<>(); // need to put/get data in FIFO
class Producer implements Runnable {
private final int totalTasks;
Producer(int totalTasks) {
this.totalTasks = totalTasks;
}
#Override
public void run() {
try {
for (int i = 0; i < totalTasks + 1; i++) {
emptyCount.acquire();
mutex.acquire();
if (i == totalTasks) {
list.offer(EOF);
} else {
// add a valid value
list.offer(i);
System.out.println("Produced: " + i);
}
mutex.release();
fillCount.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
#Override
public void run() {
try {
boolean finished = false;
while (!finished) {
fillCount.acquire();
mutex.acquire();
int item = list.poll();
if (EOF.equals(item)) {
// do not consume this item because it means EOF
finished = true;
} else {
// it's a valid value, consume it.
System.out.println("Consumed: " + item);
}
mutex.release();
emptyCount.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void runTest() {
int numProducer = 3;
int tasksPerProducer = 10;
for (int i = 0; i < numProducer; i++) {
new Thread(new Producer(tasksPerProducer)).start();
}
int numConsumer = numProducer; // producers will put N EOFs to kill N consumers.
for (int i = 0; i < numConsumer; i++) {
new Thread(new Consumer()).start();
}
}
public static void main(String[] args) throws IOException {
Test4 t = new Test4();
t.runTest();
}
}
Instead of using two semaphores why dont you use a single semaphore to such that the synchronization is made between threads link
Additional you can use ArrayBlockingQueue which are thread safe to properly demonstrate the Producer Consumer Problem.
I have a program that loads slowly, which I guess is due to the amount of image resources I have to load at the beginning. I thought multi-threading would help, but now I'm not so sure. Here is my automatic multi-threading method.
private static Thread[] t;
private static int currentThreads;
public static void loadWithThreads(Object[] array, IntegerRunnable r) {
final int threads = Runtime.getRuntime().availableProcessors();
t = new Thread[threads];
for (int i = 0; i < threads; i ++) {
t[i] = new Thread("HMediaConverter") {
final int id = currentThreads;
int items = (array.length / threads) * currentThreads;
#Override
public void run() {
super.run();
for (int i = items; i < (items + (array.length / threads)); i ++) {
r.run(i);
}
//Recycle this thread so it can be used for another time.
try {
t[id].join();
lock.notifyAll();
currentThreads --;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t[i].setPriority(Thread.MAX_PRIORITY);
t[i].start();
currentThreads ++;
}
}
And here is my image loading code:
public static ImageIcon loadImageIcon(String path) {
return new ImageIcon(ImageIO.read(Tools.class.getClassLoader().getResource(path));
}
Surely there is a way to speed things up? I'm running this on a perfectly good Intel i5, it shouldn't be this slow, so it must be my code.
Loading 113 images of a total of 159.14mb with...
public static void loadWithoutThreads(File[] array) {
for (File file : array) {
try {
ImageIO.read(file);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Took ~15s
With...
public static void loadWithThreads(File[] array) {
final int threads = Runtime.getRuntime().availableProcessors();
t = new Thread[threads];
CountDownLatch latch = new CountDownLatch(threads);
for (int i = 0; i < threads; i++) {
t[i] = new Thread("HMediaConverter") {
final int id = currentThreads;
int items = (array.length / threads) * currentThreads;
#Override
public void run() {
try {
System.out.println("Starting " + id);
for (int i = items; i < (items + (array.length / threads)); i++) {
try {
System.out.println(i + ": " + array[i]);
ImageIO.read(array[i]);
} catch (IOException ex) {
ex.printStackTrace();
}
}
} finally {
latch.countDown();
}
}
};
t[i].setPriority(Thread.MAX_PRIORITY);
System.out.println("Start " + i);
t[i].start();
currentThreads++;
}
try {
latch.await();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
took ~11s
With...
public static void loadWithExecutor(File[] images) {
ExecutorService service = Executors.newFixedThreadPool(2);
List<ImageLoadingTask> tasks = new ArrayList<>(images.length);
for (File file : images) {
tasks.add(new ImageLoadingTask(file));
}
try {
List<Future<BufferedImage>> results = service.invokeAll(tasks);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
service.shutdown();
}
public static class ImageLoadingTask implements Callable<BufferedImage> {
private File file;
public ImageLoadingTask(File file) {
this.file = file;
}
#Override
public BufferedImage call() throws Exception {
return ImageIO.read(file);
}
}
Took ~7s
The ExecutorService is more efficient because when one thread is processing a larger file, the other can be processing a number of small files. This is achieved by pooling the threads that aren't doing any work until they are needed, allowing a thread to perform a lot of short work, while the other thread(s) are also busy. You don't need to wait as long
Have a look at Executors for more details
The following is a re-write that should work that is close to what the op wrote. A re-write into A fixed-size thread pool would probably be better.
//import java.util.concurrent.atomic.AtomicInteger;
private static Thread[] t;
private static AtomicInteger completedLoads = new AtomicInteger(0);
public static void loadWithThreads(Object[] array, IntegerRunnable r) {
final int threads = Runtime.getRuntime().availableProcessors();
t = new Thread[threads];
completedLoads = new AtomicInteger(0);
int targetLoads = array.length;
int itemsPerThread = (array.length / threads);
for (int i = 0; i < threads; i ++) {
t[i] = new Thread("HMediaConverter" + i) {
int startItem = itemsPerThread * i;
#Override
public void run() {
super.run();
for (int i = startItem; i < startItem + itemsPerThread; i ++) {
try {
r.run(i);
}
finally {
completedLoads.incrementAndGet();
}
}
}
};
t[i].setPriority(Thread.MAX_PRIORITY);
t[i].start();
}
// Wait for the images to load
while (completedLoads.get() < targetLoads)
{
try {
Thread.sleep(100);
}
catch (InterruptedException ie) {
// ignore
}
}
}
Isolate which part does the slowing down - e.g by running System.currentTimeMillis() btween major segmnst then show us where is the biggest time - or show us all the program.
Threads handling as noted is questionable and you shouldn't use methods such as join etc out of the box unless you have seen it sometwhere provably working.
So post times and we'll take it from there - it could be the images it could be the threads
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);
}
}
}
}
}