As with basically every exchanger task, I have a producer filling up an empty buffer2, a consumer clearing a full buffer1 and when each thread is done, they should exchange their respective buffers.
I am really unsure about where and how to apply the exchange. I defined readyconsumer and readyproducer as booleans, so that a third thread can check whether it's time to exchange the buffers once both are true. This should solve the problem I had doing it with two threads, where the program was stuck with both threads at wait() (which it unfortunately still is).
This is what the code looks like at the moment. Can anyone help me in which class I have to exchange and at what point in the code? Thank you very much in advance!
class Buffer {
static boolean readyconsumer, readyproducer = false;
volatile int count; // number of put actions
static int max = 10;
Buffer() {
count = 0;
}
public synchronized void put() {
if (count == max) {
readyproducer = true;
System.out.println(" wait ");
try {
wait();
} catch (InterruptedException e) {
}
}
count++;
System.out.println("put " + count);
notifyAll();
}
public synchronized void get() {
if (count == 0) {
readyconsumer = true;
System.out.println(" wait");
try {
wait();
} catch (InterruptedException e) {
}
}
count--;
System.out.println("get " + count);
notifyAll();
}
}
class CheckandSwitch extends ProdCon {
public void run() {
while (true) {
if (Buffer.readyconsumer && Buffer.readyproducer) {
try {
ProdCon.buffer2 = exchanger.exchange(ProdCon.buffer1);
ProdCon.buffer1 = exchanger.exchange(ProdCon.buffer2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Buffer.readyconsumer = false;
Buffer.readyproducer = false;
buffer1.count = 0;
buffer2.count = 10;
notifyAll();
}
}
}
}
class Consumer extends ProdCon {
static Buffer buffer;
Consumer(Buffer b) {
super();
buffer = b;
b.count = 10;
}
public void run() {
while (true) {
consume();
buffer.get();
}
}
private void consume() {
System.out.println("consume");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
class Producer extends ProdCon {
static Buffer buffer;
Producer(Buffer b) {
super();
buffer = b;
b.count = 0;
}
public void run() {
while (true) {
produce();
buffer.put();
}
}
private void produce() {
System.out.println("produce ");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
}
import java.util.concurrent.*;
public class ProdCon extends Thread {
static Exchanger<Buffer> exchanger = new Exchanger<Buffer>();
static Buffer buffer1, buffer2 = null;
public static void main(String[] args) {
buffer1 = new Buffer();
buffer2 = new Buffer();
new Consumer(buffer1).start();
new Producer(buffer2).start();
new CheckandSwitch().start();
}
}
You could use an Exchanger.
Here's the code from the javadoc tweaked into a working example.
class DataBuffer<T> {
T data = null;
public boolean isFull() {
return data != null;
}
public boolean isEmpty() {
return data == null;
}
public T get() {
T d = data;
data = null;
return d;
}
public void put(T data) {
this.data = data;
}
}
class FillAndEmpty {
Exchanger<DataBuffer<Integer>> exchanger = new Exchanger<>();
DataBuffer<Integer> initialEmptyBuffer = new DataBuffer<>();
DataBuffer<Integer> initialFullBuffer = new DataBuffer<>();
int countDown = 10;
class FillingLoop implements Runnable {
#Override
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null && countDown > 0) {
addToBuffer(currentBuffer);
if (currentBuffer.isFull()) {
currentBuffer = exchanger.exchange(currentBuffer);
}
}
} catch (InterruptedException ex) {
}
}
private void addToBuffer(DataBuffer<Integer> currentBuffer) {
currentBuffer.put(countDown--);
}
}
class EmptyingLoop implements Runnable {
#Override
public void run() {
DataBuffer<Integer> currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.isEmpty()) {
currentBuffer = exchanger.exchange(currentBuffer);
}
}
} catch (InterruptedException ex) {
}
}
private void takeFromBuffer(DataBuffer<Integer> currentBuffer) {
System.out.println(currentBuffer.get());
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}
public void test() {
System.out.println("Hello");
new FillAndEmpty().start();
}
Related
I don't see any problem with this code, but the result doesn't display in the console window in eclipse.
What's the problem?
class Buffer{
private int data;
private boolean empty = true;
public synchronized int get() {
while(empty) {
try {
wait();
} catch (InterruptedException e) {
}
}
empty = true;
notifyAll();
return data;
}
public synchronized void put(int data) {
while (!empty) {
try {
wait();
} catch (InterruptedException e) {
}
}
empty = false;
this.data = data;
notifyAll();
}
}
class Producer implements Runnable{
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i=0; i<0; i++) {
buffer.put(i);
System.out.println("Producer: " + i + "th cake produced.");
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
}
}
}
}
class Consumer implements Runnable{
private Buffer buffer;
public Consumer(Buffer drop) {
this.buffer = drop;
}
public void run() {
for(int i=0; i<10; i++) {
int data = buffer.get();
System.out.println("Consumer: " + data + "th cake comsumed.");
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
}
}
}
}
public class ProducerConsumerTest {
public static void main(String[] args) {
Buffer buffer = new Buffer();
(new Thread(new Producer(buffer))).start();
(new Thread(new Consumer(buffer))).start();
}
}
In the run() method of the producer you have bad for loop
for (int i=0; i<0; i++)
but it should be
for (int i=0; i<10; i++)
That was probably a typo :)
I have just started learning threads and pretty new to it.I'm trying to print alphabets and numbers one after the other.I have synchronized them using a flag but of no use.
public class Alphabets {
public static void main(String[] args) {
AN an= new AN(false);
Thread t1=new Thread(new Runnable() {
#Override
public void run() {
try {
an.Alpha();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2= new Thread(new Runnable() {
#Override
public void run() {
try {
an.numbers();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
...
class AN
{
boolean flag;
AN(boolean flag)
{
this.flag=flag;
}
synchronized void Alpha() throws InterruptedException
{
if(flag==false)
{
for(char i='A'; i<='Z';i++)
{
System.out.println(+i);
notifyAll();
flag=true;
}
}
else
{
wait();
}
}
synchronized void numbers() throws InterruptedException
{
if(flag==true)
{
for(int i=1;i<=26;i++)
{
System.out.println(+i);
notifyAll();
flag=false;
}
}
else
{
wait();
}
}
}
My desired output is : a1b2c3d4....
My console output is : abcd...1234...
Can anybody point out the mistake since I'm unable to synchronize these two threads.
Change class AN to check the flag in while loop.
public class AN {
boolean flag;
AN(boolean flag) {
this.flag = flag;
}
synchronized void Alpha() throws InterruptedException {
for(char i = 'A'; i <= 'Z'; i++) {
while(flag == true) {
wait();
}
System.out.println(i);
notifyAll();
flag = true;
}
}
synchronized void numbers() throws InterruptedException {
for(int i = 1; i <= 26; i++) {
while(flag == false) {
wait();
}
System.out.println(i);
notifyAll();
flag = false;
}
}
Well, what you want is more or less pipelining, therefore the threads need to know when they are allowed to work.
I'd therefore use a Queue to await the input on one thread and wait for it to be set in the other thread.
Class AN:
import java.util.concurrent.BlockingQueue;
class AN
{
BlockingQueue<Boolean> input;
BlockingQueue<Boolean> output;
AN(BlockingQueue<Boolean> input, BlockingQueue<Boolean> output)
{
this.input = input;
this.output = output;
}
void Alpha() throws InterruptedException
{
for (char i = 'a'; i <= 'z'; i++) {
input.take();
System.out.print(i);
output.put(Boolean.TRUE);
}
}
void numbers() throws InterruptedException
{
for (int i = 1; i <= 26; i++) {
input.take();
System.out.print(i);
output.put(Boolean.TRUE);
}
}
}
Class Test (or where your main is):
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Test
{
public static void main(String[] args) throws InterruptedException
{
BlockingQueue<Boolean> input = new LinkedBlockingQueue<>();
BlockingQueue<Boolean> output = new LinkedBlockingQueue<>();
AN an1 = new AN(output, input);
AN an2 = new AN(input, output);
output.add(Boolean.TRUE);
Thread t1 = new Thread(new Runnable()
{
#Override
public void run()
{
try {
an1.Alpha();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable()
{
#Override
public void run()
{
try {
an2.numbers();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
Outputs: a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z26
You can achieve this by using BlockingQueue and Object's wait and notify methods.
public class AlphaNum {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(10);
AtomicBoolean flag = new AtomicBoolean(Boolean.TRUE);
Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
for(int i=1;i<=26;i++){
synchronized (lock){
while (flag.get()){
lock.wait();
}
System.out.print(i);
flag.set(Boolean.TRUE);
lock.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
for(char c='A';c<='Z';c++){
synchronized (lock){
while (!flag.get()){
lock.wait();
}
System.out.print(c);
flag.set(Boolean.FALSE);
lock.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
The above code prints a1b2c3d4.......z26
There are many ways to achieve this, Below one is one of them.
package interview;
public class TestAplhaAndNumberPrinterThreads {
// created object as static so we can access print method of this class from thread's run methods
public static TestAplhaAndNumberPrinterThreads output = new TestAplhaAndNumberPrinterThreads();
private final Object syncer = new Object();
private int state = 0;
public void print(char character) throws InterruptedException {
synchronized (syncer) {
while (true) {
if (state == 0) {
System.out.print(character + ", ");
state = 1;
syncer.notify();
return;
} else {
syncer.wait();
}
}
}
}
public void print(int number) throws InterruptedException {
synchronized (syncer) {
while (true) {
if (state == 1) {
System.out.print(number + ", ");
state = 0;
syncer.notify();
return;
} else {
syncer.wait();
}
}
}
}
public static void main(String[] args) {
NumberPrinter numberPrinter = new NumberPrinter();
AlphabetsPrinter alphabetsPrinter = new AlphabetsPrinter();
numberPrinter.start();
alphabetsPrinter.start();
}
}
class NumberPrinter extends Thread {
#Override
public void run() {
try {
for (int i = 1; i <= 26; i++) {
TestAplhaAndNumberPrinterThreads.output.print(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class AlphabetsPrinter extends Thread {
#Override
public void run() {
try {
for (char i = 'a'; i <= 'z'; i++) {
TestAplhaAndNumberPrinterThreads.output.print(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// output: a, 1, b, 2, c, 3, d, 4, e, 5, f, 6, g, 7, h, 8, i, 9, j, 10, k, 11, l, 12, m, 13, n, 14, o, 15, p, 16, q, 17, r, 18, s, 19, t, 20, u, 21, v, 22, w, 23, x, 24, y, 25, z, 26,
I think the big things is for you to know, how to use break points to debug in IDE and why your code was not working. You can see the process of your code will run. I have post the picture at the last and this code which will work like your wish
class AN {
boolean flag;
AN(boolean flag) {
this.flag = flag;
}
synchronized void Alpha() throws InterruptedException {
if (flag == false) {
for (char i = 'A'; i <= 'Z'; i++) {
System.out.println(i);
flag = true;
notify();
wait();
}
}
}
synchronized void numbers() throws InterruptedException {
if (flag == true) {
for (int i = 1; i <= 26; i++) {
System.out.println(+i);
flag = false;
notify();
wait();
}
}
}
}
enter image description here
I have 3 threads
1st printing A
2nd printing B
3rd printing C
I want to print in sequence A B C A B C A B C and so on.....
So I wrote the program below, but I am not able to achieve the same.
I am aware of the problem that when status=1 at that time say for example B1 and C1 thread are waiting and when I do notifyAll() both waiting thread wake up and depending on CPU allocation it might print B or C.
in this case I want only B to be printed after A.
what modification I need to do.
public class NotifyAllExample {
int status=1;
public static void main(String[] args) {
NotifyAllExample notifyAllExample = new NotifyAllExample();
A1 a=new A1(notifyAllExample);
B1 b=new B1(notifyAllExample);
C1 c=new C1(notifyAllExample);
a.start();
b.start();
c.start();
}
}
class A1 extends Thread{
NotifyAllExample notifyAllExample;
A1(NotifyAllExample notifyAllExample){
this.notifyAllExample = notifyAllExample;
}
#Override
public void run() {
try{
synchronized (notifyAllExample) {
for (int i = 0; i < 100; i++) {
if(notifyAllExample.status!=1){
notifyAllExample.wait();
}
System.out.print("A ");
notifyAllExample.status = 2;
notifyAllExample.notifyAll();
}
}
}catch (Exception e) {
System.out.println("Exception 1 :"+e.getMessage());
}
}
}
class B1 extends Thread{
NotifyAllExample notifyAllExample;
B1(NotifyAllExample notifyAllExample){
this.notifyAllExample = notifyAllExample;
}
#Override
public void run() {
try{
synchronized (notifyAllExample) {
for (int i = 0; i < 100; i++) {
if(notifyAllExample.status!=2){
notifyAllExample.wait();
}
System.out.print("B ");
notifyAllExample.status = 3;
notifyAllExample.notifyAll();
}
}
}catch (Exception e) {
System.out.println("Exception 2 :"+e.getMessage());
}
}
}
class C1 extends Thread{
NotifyAllExample notifyAllExample;
C1(NotifyAllExample notifyAllExample){
this.notifyAllExample = notifyAllExample;
}
#Override
public void run() {
try{
synchronized (notifyAllExample) {
for (int i = 0; i < 100; i++) {
if(notifyAllExample.status!=3){
notifyAllExample.wait();
}
System.out.print("C ");
notifyAllExample.status = 1;
notifyAllExample.notifyAll();
}
}
}catch (Exception e) {
System.out.println("Exception 3 :"+e.getMessage());
}
}
}
Convert those IF statements to WHILE statements to get the desired behavior:
if (notifyAllExample.status != 2){
notifyAllExample.wait();
}
to
while (notifyAllExample.status != 2){
notifyAllExample.wait();
}
This will ensure that if a thread is notified, it won't go out of the while loop until the status value is what it expects.
Also, mark status as volatile so that the threads won't have a local copy.
public class RunThreadsInOrder implements Runnable {
static int numThread = 1;
static int threadAllowedToRun = 1;
int myThreadID;
private static Object myLock = new Object();
public RunThreadsInOrder() {
this.myThreadID = numThread++;
System.out.println("Thread ID:" + myThreadID);
}
#Override
public void run() {
synchronized (myLock) {
while (myThreadID != threadAllowedToRun) {
try {
myLock.wait();
} catch (InterruptedException e) {
} catch (Exception e) {}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("myThreadID is running: " + myThreadID);
myLock.notifyAll();
threadAllowedToRun++;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread t1 = new Thread(new RunThreadsInOrder());
Thread t2 = new Thread(new RunThreadsInOrder());
Thread t3 = new Thread(new RunThreadsInOrder());
Thread t4 = new Thread(new RunThreadsInOrder());
Thread t5 = new Thread(new RunThreadsInOrder());
Thread t6 = new Thread(new RunThreadsInOrder());
Thread t7 = new Thread(new RunThreadsInOrder());
t7.start();
t6.start();
t5.start();
t4.start();
t3.start();
t2.start();
t1.start();
}
}
public class Main {
public static void main(String[] args) throws IOException{
Thread t1 = new Thread(new A(), "1");
Thread t2 = new Thread(new A(), "2");
Thread t3 = new Thread(new A(), "3");
t1.start();
try{
t1.join();
}catch (Exception e){
}
t2.start();
try{
t2.join();
}catch (Exception e){
}
t3.start();
try{
t3.join();
}catch (Exception e){
}
}
}
class A implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName());
}
}
or you can use Executor Framework
public class Sequence {
int valve = 1;
public static void main(String[] args){
Sequence s = new Sequence();
ExecutorService es = Executors.newFixedThreadPool(3);
List<Runnable> rList = new ArrayList<>();
rList.add(new A(s));
rList.add(new B(s));
rList.add(new C(s));
for(int i = 0; i < rList.size(); i++){
es.submit(rList.get(i));
}
es.shutdown();
}
}
class A implements Runnable{
Sequence s;
A(Sequence s){
this.s = s;
}
public void run(){
synchronized (s) {
for (int i = 0; i < 10; i++) {
while (s.valve != 1) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
s.valve = 2;
s.notifyAll();
}
}
}
}
class B implements Runnable{
Sequence s;
B(Sequence s){
this.s = s;
}
public void run() {
synchronized (s) {
for (int i = 0; i < 10; i++) {
while (s.valve != 2) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
s.valve = 3;
s.notifyAll();
}
}
}
}
class C implements Runnable{
Sequence s;
C(Sequence s){
this.s = s;
}
public void run() {
synchronized (s) {
for(int i = 0; i < 10; i++) {
while (s.valve != 3) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
s.valve = 1;
s.notifyAll();
}
}
}
}
In the first case the join for each thread causes the threads to wait for one another. In the second case a list stores the threads and executor executes them one after another creating 3 threads
Another way to do this is where only one runnable class is present and communication between thread is done via static variable in the main class and a variable in the runnable class
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Seq {
int i = 1;
public static void main(String[] args){
Seq s = new Seq();
Common c1 = new Common(s, 1);
Common c2 = new Common(s, 2);
Common c3 = new Common(s, 3);
List<Runnable> l = new ArrayList<>();
l.add(c1);
l.add(c2);
l.add(c3);
ExecutorService es = Executors.newFixedThreadPool(3);
for(int i = 0; i < 3; i++){
es.submit(l.get(i));
}
es.shutdown();
}
}
class Common implements Runnable{
Seq s;
int o;
Common(Seq s, int o){
this.s = s;
this.o = o;
}
public void run(){
synchronized (s) {
for (int z = 0; z < 100; z++) {
if(s.i > 3)
s.i = 1;
while (s.i != o) {
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(o);
s.i++;
s.notifyAll();
}
}
}
}
I was asked to write a similar program in an interview with the added condition that it should be extensible in a way that we can provide our own count of threads and they should print characters with the first thread printing 'A' and then the subsequent threads printing B, C, D and so on. Here's how I did it.
public class AlternateCharPrinter {
public static char ch = 65;
private static void createAndStartThreads(int count) {
Object lock = new Object();
for (int i = 0; i < count; i++) {
new Thread(new AlternateCharRunner((char) (65 + i), lock)).start();
}
}
public static void main(String[] args) {
createAndStartThreads(4);
}
}
class AlternateCharRunner implements Runnable {
private char ch;
private Object lock;
private static int runnerCount;
public AlternateCharRunner(char ch, Object lock) {
this.ch = ch;
this.lock = lock;
runnerCount++;
}
#Override
public void run() {
while (true) {
synchronized (lock) {
while (ch != AlternateCharPrinter.ch) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(AlternateCharPrinter.ch++);
if (AlternateCharPrinter.ch == (65 + runnerCount)) {
AlternateCharPrinter.ch = 65;
}
lock.notifyAll();
}
}
}
}
You need to replace
if (notifyAllExample.status!=1)
with
while (notifyAllExample.status!=1)
and same thing in the other 2 classes. If not, then as soon as the wait exits the thread continues without knowing if it is its turn.
Replace:
if(notifyAllExample.status!=1){
notifyAllExample.wait();
}
with:
while(notifyAllExample.status!=1){
notifyAllExample.wait();
}
in all classes accordingly.
The simplest solution to solve this can be following way:
public class PrintInOrder implements Runnable {
private int valueToPrint;
private int id;
private static int turn = 1;
private static int RESET_TURN_THRESHOLD = 3;
public PrintInOrder() {
this.valueToPrint = -1;
}
public PrintInOrder(int id, int val) {
this.id = id;
this.valueToPrint = val;
}
#Override
public void run() {
while(true) {
if (turn == this.id) {
System.out.println(Thread.currentThread().getName() + "::::" + valueToPrint);
turn++;
}
if (turn > RESET_TURN_THRESHOLD) {
turn = 1;
}
}
}
public static void main(String []args) {
Thread t1 = new Thread(new PrintInOrder(1, 1));
t1.setName("THREAD-1");
t1.start();
Thread t2 = new Thread(new PrintInOrder(2, 2));
t2.setName("THREAD-2");
t2.start();
Thread t3 = new Thread(new PrintInOrder(3, 3));
t3.setName("THREAD-3");
t3.start();
}
}
/*
OUTPUT::::
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
THREAD-1::::1
THREAD-2::::2
THREAD-3::::3
...
*/
Here is my solution -
I have created three threads each thread knows what it needs to print and what comes after it.
I have also created a Class NLock which holds the next word which needs to be printed.
Whenever a thread is able to acquire NLock lock then it checks
if it's his turn if yes then it prints the word and set the next value to be printed in NLock or else it waits till it's his turn
public class SynchronizeThreeThreads {
public static void main(String args[]) throws InterruptedException {
NLock lock=new NLock("A");
Thread a =new Thread(new PrintInOrder("A","B",lock));
Thread b =new Thread(new PrintInOrder("B","C",lock));
Thread c =new Thread(new PrintInOrder("C","A",lock));
a.start();
b.start();
c.start();
c.join(); // Once all is done main thread will exit
System.out.println("Done");
}
}
class NLock{
private String value;
public NLock(String value) {
this.value=value;
}
public String getValue() {
return value;
}
public void setValue(String next) {
this.value=next;
}
}
class PrintInOrder implements Runnable{
private String word;
private String next;
private NLock lock;
public PrintInOrder(String word, String next,NLock lock){
this.word=word;
this.next=next;
this.lock=lock;
}
#Override
public void run() {
int i=0;
while(i<3) {
synchronized (lock) {
try {
//Check if it's my turn
if(lock.getValue().equals(word)) {
System.out.println(this.word);
//Set what next needs to be printed
//So that when that thread wakes up it knows that it's his turn
lock.setValue(next);
i++;
lock.notifyAll();
Thread.sleep(100);
}
else //Nope not my turn wait
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Below is the output
A
B
C
A
B
C
A
B
C
Done
This is my attempt to solve the same. Any suggestions are welcome. This is the complete running code.
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
#Slf4j
public class SeqExecution {
static class SeqThread extends Thread {
private static final Object lock = new Object();
private static final AtomicInteger AUTO_COUNTER = new AtomicInteger();
private static final TrackExecution trackExecution = new TrackExecution();
private final int seqNo;
SeqThread(Runnable runnable) {
super(runnable);
this.seqNo = AUTO_COUNTER.getAndIncrement();
}
#SneakyThrows
#Override
public void run() {
while (true) {
synchronized (lock) {
while (trackExecution.CUR_EXECUTION.get() != this.seqNo) {
try {
lock.wait(100);
} catch (Exception e) {}
}
//log.info("Thread: {} is running", this.seqNo);
super.run();
sleep(1000);
trackExecution.increment();
lock.notifyAll();
}
}
}
static class TrackExecution {
private final AtomicInteger CUR_EXECUTION = new AtomicInteger();
int get() {
return CUR_EXECUTION.get();
}
synchronized void increment() {
var val = CUR_EXECUTION.incrementAndGet();
if (val >= SeqThread.AUTO_COUNTER.get()) {
CUR_EXECUTION.set(0);
}
}
}
}
public static void main(String[] args) {
final var seqThreads = List.of(new SeqThread(() -> System.out.print("A ")),
new SeqThread(() -> System.out.print("B ")),
new SeqThread(() -> System.out.print("C ")));
seqThreads.forEach(Thread::start);
seqThreads.forEach(t -> {
try {
t.join();
} catch (Exception e) {
log.warn(e.getMessage(), e);
}
});
}
}
I think it's simpler to achieve this using join.
Example:
public static void main(String[] args) {
final Thread t1 = new Thread("t1") {
#Override
public void run() {
System.out.println("i am thread: " + Thread.currentThread().getName());
}
};
final Thread t2 = new Thread(t1, "t2") {
#Override
public void run() {
t1.start();
try {
t1.join();
} catch ( InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("i am thread: " + Thread.currentThread().getName());
}
};
Thread t3 = new Thread(t2, "t3") {
#Override
public void run() {
t2.start();
try {
t2.join();
} catch ( InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("i am thread: " + Thread.currentThread().getName());
}
};
t3.start();
}
Here is my solution please try and let me know
package thread;
class SyncPrinter {
public static void main(String[] args) {
SyncPrinterAction printAction1 = new SyncPrinterAction(new int[]{1,5,9,13}, true);
SyncPrinterAction printAction2 = new SyncPrinterAction(new int[]{2,6,10,14}, true);
SyncPrinterAction printAction3 = new SyncPrinterAction(new int[]{3,7,11,15}, true);
SyncPrinterAction printAction4 = new SyncPrinterAction(new int[]{4,8,12,16}, false);
printAction1.setDependentAction(printAction4);
printAction2.setDependentAction(printAction1);
printAction3.setDependentAction(printAction2);
printAction4.setDependentAction(printAction3);
new Thread(printAction1, "T1").start();;
new Thread(printAction2, "T2").start();
new Thread(printAction3, "T3").start();
new Thread(printAction4, "T4").start();
}
}
class SyncPrinterAction implements Runnable {
private volatile boolean dependent;
private SyncPrinterAction dependentAction;
int[] data;
public void setDependentAction(SyncPrinterAction dependentAction){
this.dependentAction = dependentAction;
}
public SyncPrinterAction( int[] data, boolean dependent) {
this.data = data;
this.dependent = dependent;
}
public SyncPrinterAction( int[] data, SyncPrinterAction dependentAction, boolean dependent) {
this.dependentAction = dependentAction;
this.data = data;
this.dependent = dependent;
}
#Override
public void run() {
synchronized (this) {
for (int value : data) {
try {
while(dependentAction.isDependent())
//System.out.println("\t\t"+Thread.currentThread().getName() + " :: Waithing for dependent action to complete");
wait(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
dependentAction.setDependent(true);
System.out.println(Thread.currentThread().getName() + " :: " +value);
dependent = false;
}
}
}
private void setDependent(boolean dependent) {
this.dependent = dependent;
}
private boolean isDependent() {
return dependent;
}
}
I'm trying to solve the producer consumer problem with threads in java, but the code won't run in parallell/concurrently. The producer always fills up the buffer completely before the consumer starts to consume, and I don't get why. The point is trying to do it using only synchronized blocks, wait() and notify().
Main :
String [] data = {"Fisk", "Katt", "Hund", "Sau", "Fugl", "Elg", "Tiger",
"Kameleon", "Isbjørn", "Puma"};
ProducerConsumer pc = new ProducerConsumer(5);
Thread[] thrds = new Thread[2];
thrds[0] = new Thread(new MyThread1(pc, data)); // producer
thrds[1] = new Thread(new MyThread2(pc)); // consumer
thrds[0].start();
thrds[1].start();
for(int i = 0; i < 2; i++) { // wait for all threads to die
try {
thrds[i].join();
}
catch (InterruptedException ie) {}
}
System.exit(0);
ProducerConsumer.java:
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer implements Runnable {
private int bufferSize;
private Queue<String> buffer;
public ProducerConsumer(int size) {
bufferSize = size;
buffer = new LinkedList<String>();
}
public void produce(String item) throws InterruptedException {
synchronized(buffer) {
while (buffer.size() >= bufferSize) {
try {
System.out.println("Full buffer. Waiting for consumer...");
buffer.wait();
}catch (Exception e) {}
}
buffer.add(item);
System.out.println("Producer is putting " + item + " in the buffer");
buffer.notify();
}
}
public void consume() throws InterruptedException {
synchronized (buffer) {
while (buffer.size() == 0) {
try {
System.out.println("Empty buffer. Waiting for production...");
buffer.wait();
}catch (Exception e) {}
}
System.out.println("Consumer is consuming " + buffer.remove() + ".");
buffer.notify();
}
}
#Override
public void run() {
}
}
MyThread1 :
/*
* PRODUCER - Thread
*/
public class MyThread1 implements Runnable {
private String [] data;
private ProducerConsumer pc;
public MyThread1(ProducerConsumer pc, String [] data) {
this.pc = pc;
this.data = data;
}
#Override
public void run() {
for (int i = 0; i < data.length; i++) {
try {
pc.produce(data[i]);
} catch (InterruptedException ex) {}
}
}
}
MyThread2:
//THE CONSUMER - Thread
public class MyThread2 implements Runnable{
private ProducerConsumer pc;
public MyThread2(ProducerConsumer pc) {
this.pc = pc;
}
//Run consume
#Override
public void run() {
while (true) {
try {
pc.consume();
Thread.sleep(2);
}
catch(InterruptedException e) {}
}
}
}
On recent machines, with short queues like this, you will never see actual multithreading effects like, in this case, producer and consumer taking turns unless you slow both of them down a bit. You only slowed down the consumer. Instead of using a short array, put a million Integers in a queue and see what happens.
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ProduserConsumerDemo {
public static void main(String[] args) {
List<Integer> list = new CopyOnWriteArrayList<>();
int size = 5;
Producer producer = new Producer(list, size);
Consumer consumer = new Consumer(list);
Thread t1 = new Thread(producer, "Producer");
Thread t2 = new Thread(consumer, "Consumer");
t1.start();
t2.start();
}
}
class Producer implements Runnable {
private final List<Integer> list;
private final int size;
public Producer(List<Integer> list, final int size) {
this.list = list;
this.size = size;
}
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void produce() throws InterruptedException {
int i = 0;
while (i >= 0) {
synchronized (list) {
while (list.size() == size) {
System.out.println(
"List is full." + Thread.currentThread().getName() + " is waiting. Size:" + list.size());
list.wait();
}
System.out.println("Produce :" + i);
list.add(i++);
Thread.sleep(50);
list.notify();
}
}
}
}
class Consumer implements Runnable {
private final List<Integer> list;
public Consumer(List<Integer> list) {
this.list = list;
}
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void consume() throws InterruptedException {
while (true) {
synchronized (list) {
while (list.isEmpty()) {
System.out.println(
"List is empty. " + Thread.currentThread().getName() + " is waiting. Size:" + list.size());
list.wait();
}
System.out.println("Consumed item:" + list.remove(0));
Thread.sleep(50);
list.notify();
}
}
}
}
I have a problem when scheduling two threads (ReadData and WriteData). It seems that I can't notify after wait.
Here is my class which I define and call:
Buffer: The buffer I use to read / write data. I synch this class.
public class Buffer {
// Size of buffer we use to store data
public static final int SIZE = 10;
// Data of buffer.
private int[] values;
// Count of element in data.
private int count;
// Instance of buffer, for singleton pattern
private static Buffer instance = null;
// A signal show data in use (busy) or not
private static Object mutex = new Object();
// Constructor of buffer
private Buffer(){
values = new int[SIZE];
count = 0;
}
// Get instance of buffer.
public static Buffer getInstance(){
if(instance == null){
synchronized (mutex) {
if(instance == null) instance = new Buffer();
}
}
return instance;
}
public void addValue(int value){
synchronized (mutex) {
if(count >= SIZE) return;
values[count++] = value;
}
}
// Return current data and then reset buffer.
public int[] getValues(){
synchronized (mutex) {
if(count == 0) return null;
int[] values = new int[count];
System.arraycopy(this.values, 0, values, 0, count);
count = 0;
return values;
}
}
public int getCount(){
synchronized (mutex) {
return count;
}
}
}
ReadData: This class I use to store data into the buffer.
import java.util.Random;
public class ReadData implements Runnable {
Buffer buffer = Buffer.getInstance();
#Override
public synchronized void run() {
Random random = new Random();
while(true){
if(buffer.getCount() >= Buffer.SIZE){
try {
System.out.println("Read: is waiting. . .");
mState.readIsWaiting();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Read: storing data");
buffer.addValue(random.nextInt(Buffer.SIZE) + 1);
}
}
}
public interface ReadState{
void readIsWaiting();
}
private ReadState mState;
public void setReadState(ReadState state){
mState = state;
}
public synchronized void makeNotify() {
notifyAll();
}
}
WriteData: This class I use to get data from the buffer
public class WriteData implements Runnable {
Buffer buffer = Buffer.getInstance();
#Override
public synchronized void run() {
while(true){
if(buffer.getCount() == 0){
try {
System.out.println("Write: is waiting. . .");
mState.writeIsWaiting();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
int[] getdata = buffer.getValues();
System.out.println("first data: " + getdata[0]);
}
}
}
public interface WriteState{
void writeIsWaiting();
}
private WriteState mState;
public void setWriteState(WriteState state){
mState = state;
}
public synchronized void makeNotify() {
notifyAll();
}
}
MyThread: The thread I use to start read/write
package main;
import testing.ReadData;
import testing.WriteData;
public class MyThread implements ReadData.ReadState, WriteData.WriteState {
private ReadData read;
private WriteData write;
public void start(){
read = new ReadData();
write = new WriteData();
read.setReadState(this);
write.setWriteState(this);
new Thread(read).start();
new Thread(write).start();
}
#Override
public void writeIsWaiting() {
read.makeNotify();
}
#Override
public void readIsWaiting() {
write.makeNotify();
}
}
That's it. Sometimes it works, many times it stops and waits.
How do I solve this problem? Thanks
I think you've reversed the ReadData implementation with the WriteData. In the code shown, the ReadData thread will block if the buffer is full:
#Override
public synchronized void run() {
Random random = new Random();
while(true){
if(buffer.getCount() >= Buffer.SIZE){
try {
System.out.println("Read: is waiting. . .");
mState.readIsWaiting();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Read: storing data");
buffer.addValue(random.nextInt(Buffer.SIZE) + 1);
}
}
}
What you really need is:
#Override
public synchronized void run() {
Random random = new Random();
while(true){
if(buffer.getCount() == 0){
try {
System.out.println("Read: is waiting. . .");
mState.readIsWaiting();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Read: storing data");
buffer.addValue(random.nextInt(Buffer.SIZE) + 1);
}
}
}
Similarly, in the WriteData implementation, you should block if the buffer is full. This will happen if the reader hasn't had a chance to take the elements from the buffer. This should work for the WriteData code:
#Override
public synchronized void run() {
while(true){
if(buffer.getCount() >= Buffer.SIZE){
try {
System.out.println("Write: is waiting. . .");
mState.writeIsWaiting();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
int[] getdata = buffer.getValues();
System.out.println("first data: " + getdata[0]);
}
}
}