public class SemActionPlace {
public SemMonitor StartConsumerProducer() {
SemMonitor monitor = new SemMonitor();
List<Thread> threads = new LinkedList<>();
Thread p1 = new Thread(new Producer(monitor), "P1");
p1.start();
Thread c1 = new Thread(new Consumer(monitor), "C-odd");
c1.start();
Thread c2 = new Thread(new Consumer(monitor), "C-even");
c2.start();
threads.add(p1);
threads.add(c1);
threads.add(c2);
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return monitor;
}
}
the code work just fine when I start thread through start() - join(), however, I failed to find mistake when I try to do the same through the executor service. It's important for me to save names of the threads and mutual monitor. Please, tell me how can I execute the threads through the executor service ?
The piece of code below doen't work properly. Where is mistake ?
public SemMonitor StartConsumerProducer() {
SemMonitor monitor = new SemMonitor();
Thread p1 = new Thread(new Producer(monitor), "P1");
Thread c1 = new Thread(new Consumer(monitor), "C-odd");
Thread c2 = new Thread(new Consumer(monitor), "C-even");
ThreadPoolExecutor service = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
service.execute(p1);
service.execute(c1);
service.execute(c2);
System.out.println(service.getCompletedTaskCount());
System.out.println(service.getCompletedTaskCount());
return monitor;
}
I need one simple thing from the executor server is that I wanna that it works like simple start() - join() solution works ( first piece of code ) .
class Consumer implements Runnable {
private final SemMonitor monitor;
Consumer(SemMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
long t = System.currentTimeMillis();
long end = t + 1000;
while (System.currentTimeMillis() < end) {
consoleLog(monitor.activeThreadName,false);
if (/*monitor.semaphore.tryAcquire() && */monitor.activeThreadName.equals( Thread.currentThread().getName())) {
try {
consoleLog(String.valueOf(Thread.currentThread().getName() + " was notified "),monitor.enableLog);
monitor.semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
monitor.get(Thread.currentThread().getName());
}
try{
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer implements Runnable {
private SemMonitor monitor;
Producer(SemMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
String threadNameToWork;
Integer randNum;
long t = System.currentTimeMillis();
long end = t + 500;
while (System.currentTimeMillis() < end) {
if (monitor.semaphore.tryAcquire()) {
randNum = ((Number) (random() * 100)).intValue();
if (randNum % 2 == 0) {
threadNameToWork = "C-even";
} else {
threadNameToWork = "C-odd";
}
try {
monitor.putItem(randNum, Thread.currentThread().getName(), threadNameToWork);
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Monitor {
private double currItem;
private boolean isConsumersShouldWaitProducer = true;
private boolean isConsuming = false;
private String threadNameToWork;
synchronized void putRandNumber(double producerOutput, String producerName, String threadNameToWork) {
if (isConsumersShouldWaitProducer) {
System.out.println("Consumers wait for new Production");
}
this.threadNameToWork = threadNameToWork;
currItem = producerOutput;
System.out.println("Producer " + producerName + " putRandNumber Item: " + currItem);
if (currItem > 3) {
notifyAll();
isConsumersShouldWaitProducer = false;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void consumeRandNumber(String threadName) {
if (isConsumersShouldWaitProducer) {
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("Caught Interrupted Exception while waiting to consume currItem: " + e.getMessage());
}
}
if (isConsuming) {
try {
this.wait();
isConsuming = true;
} catch (InterruptedException e) {
System.out.println("Caught Interrupted Exception while waiting to consume currItem: " + e.getMessage());
}
}
switch (Thread.currentThread().getName()) {
/*switch (threadNameToWork) {*/
case "C-odd":
isConsuming = true;
if (currItem % 2 != 0 && threadNameToWork.equals(Thread.currentThread().getName())) {
consumeItems(threadName);
}
isConsuming = false;
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
case "C-even":
isConsuming = true;
if (currItem % 2 == 0 && threadNameToWork.equals(Thread.currentThread().getName())) {
consumeItems(threadName);
}
isConsuming = false;
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
private synchronized void consumeItems(String threadName) {
isConsumersShouldWaitProducer = true;
String randNumType = "*odd/even*";
System.out.println("Consumer:" + threadName + " consumed " + randNumType + " Items = " + currItem);
notifyAll();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You want to do something with Thread name right? The thread name you created in using new Thread will not pass into ExecutorService, but this will
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("thread-%d").build()
Then
ExecutorService exec = Executors.newSingleThreadExecutor(namedThreadFactory);
Now you have thread with name as thread-1, thread-2
OR set thread name in your run() method
Thread.currentThread().setName(myName)
To make sure your thread is finished, add this before you return the monitor,
service.shutdown();
while (!service.awaitTermination(10, TimeUnit.SECONDS)) {
log.info("Awaiting completion of threads.");
}
Related
I have the following test code for learning purposes, in which I am trying to run a producer and a consumer threads running endlessly on a blocking Q.
For some reason which I cannot understand, the output is as follows:
Produced 3001
Q puts 3001
put: Q size = 1
Produced 3002
Q puts 3002
put: Q size = 2
Q takes 3001
take: Q size = 1
Consumed 3001
The code is as follows:
#Getter #Setter #NoArgsConstructor
public class MyBlockingQ {
public BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
public Integer take() {
try {
Integer i = queue.take();
System.out.println("Q takes " + i);
System.out.println("take: Q size = " + queue.size());
return i;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
public void put(Integer produce) {
try {
System.out.println("Q puts " + produce);
queue.put(produce);
System.out.println("put: Q size = " + queue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyProducer implements Runnable {
private final MyBlockingQ queue;
private Integer i = 3000;
public MyProducer(MyBlockingQ q) {
queue = q;
}
public void run() {
while (true) {
queue.put(produce());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Integer produce() {
i++;
System.out.println("Produced " + i);
return i;
}
}
public class MyConsumer implements Runnable {
private final MyBlockingQ queue;
public MyConsumer(MyBlockingQ q) {
queue = q;
}
public void run() {
while (true) {
consume(queue.take());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void consume(Integer x) {
System.out.println("Consumed " + x);
}
}
#Test
public void testBlockingQ(){
MyBlockingQ q = new MyBlockingQ();
MyProducer p1 = new MyProducer(q);
MyConsumer c1 = new MyConsumer(q);
new Thread(p1).start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(c1).start();
}
I cannot understand why does the code stop executing after the last output line as shown above?
I am working with JavaSE-15 on latest VSCode.
Threads are terminated, when your test method reaches to the end. If you want your threads to run longer, you need to add more sleep time at the end of your test method.
#Test
public void testBlockingQ(){
MyBlockingQ q = new MyBlockingQ();
MyProducer p1 = new MyProducer(q);
MyConsumer c1 = new MyConsumer(q);
new Thread(p1).start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(c1).start();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I'm a java beginner and I write below code while learning Thread in java. I think, if I lock in Resource.set() and comment out the Lock.unlock(), the code in Resource.out() can't be executed because I can't unlock in when I want to execute out method. BTW, whether I comment out the unlock in the set() or in out(), the program will execute in this way:
Thread[Thread-1,5,main]....Produce....chicken1
Thread[Thread-2,5,main]....Consume..........chicken1
Thread[Thread-0,5,main]....Produce....chicken2
Thread[Thread-3,5,main]....Consume..........chicken2 ......
I think a long time and don't understand about it. I just learned it, maybe I have a wrong understanding,so I hope someone's help.
Please forgive my poor English. Thank you very much. My code is here:
package Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadStudying {
public static void main(String[] args) {
Resource r = new Resource();
Thread t0 = new Thread(new Producer(r));
Thread t1 = new Thread(new Producer(r));
Thread t2 = new Thread(new Consumer(r));
Thread t3 = new Thread(new Consumer(r));
t0.start();
t1.start();
t2.start();
t3.start();
}
static class Resource {
private String name;
private int count = 1;
boolean isOut = false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition consu_con = lock.newCondition();
public void set(String name) {
lock.lock();
try {
while (isOut) {
try {
pro_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
System.out.println(Thread.currentThread() + "....Produce...." + this.name);
count++;
isOut = true;
consu_con.signal();
}
finally {
lock.unlock();
}
}
public void out() {
lock.lock();
try {
while (!isOut) {
try {
consu_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "....Consume.........." + this.name);
isOut = false;
pro_con.signal();
}
finally {
//lock.unlock();
}
}
}
static class Producer implements Runnable {
Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while (true) {
r.set("chicken");
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
Resource r;
Consumer(Resource r) {
this.r = r;
}
#Override
public void run() {
while (true) {
r.out();
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
In both producer and consumer, you are calling lock.await repeatly by
while (true) {
//
}
From the doc, when you call lock.await :
The lock associated with this Condition is atomically released
So, whether you comment out lock.unlock or not, both producer and consumer will not be blocked.
P.S. Use below code to log more details about getting and releasing lock:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadStudying {
public static void main(String[] args) {
Resource r = new Resource();
Thread t0 = new Thread(new Producer(r), "Producer 1");
Thread t1 = new Thread(new Producer(r), "Producer 2");
Thread t2 = new Thread(new Consumer(r), "Consumer 1");
Thread t3 = new Thread(new Consumer(r), "Consumer 2");
t0.start();
t1.start();
t2.start();
t3.start();
}
static class Resource {
private String name;
private int count = 1;
boolean isOut = false;
Lock lock = new ReentrantLock();
Condition pro_con = lock.newCondition();
Condition consu_con = lock.newCondition();
public void set(String name) {
System.out.println(Thread.currentThread() + "before lock");
lock.lock();
System.out.println(Thread.currentThread() + "get lock");
try {
while (isOut) {
try {
System.out.println(Thread.currentThread() + "release lock");
pro_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name + count;
System.out.println(Thread.currentThread() + "....Produce...." + this.name);
count++;
isOut = true;
consu_con.signal();
}
finally {
}
}
public void out() {
System.out.println(Thread.currentThread() + "before lock");
lock.lock();
System.out.println(Thread.currentThread() + "get lock");
try {
while (!isOut) {
try {
System.out.println(Thread.currentThread() + "release lock");
consu_con.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread() + "....Consume.........." + this.name);
isOut = false;
pro_con.signal();
}
finally {
//lock.unlock();
}
}
}
static class Producer implements Runnable {
Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while (true) {
r.set("chicken");
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer implements Runnable {
Resource r;
Consumer(Resource r) {
this.r = r;
}
#Override
public void run() {
while (true) {
r.out();
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
FirstOfAll, "if I lock in Resource.set() and comment out the Lock.unlock(), the code in Resource.out() can't be executed ". This statement of yours is wrong.
Let me clarify why,
In your posted code, where out() has no unlock. I assume you have no problem that one of the Consumer threads (t2 or t3) have no problem in acquiring the lock.
So lets say t2 acquired the lock, while entering out() method and didn't release the lock while exiting out() method. But you overlooked the fact that out() method is executed in infinite loop inside run() method of Consumer Runnable. So when t2 exits out(), sleep of 500 milliseconds; its still in possession of the lock. When it enters the out() method in its next iteration, it executes Lock.lock() on the same lock it already has. Since the lock is Reentrant Lock, it proceeds and executes await() where it releases the lock; and the other threads(Producer threads) waiting on the lock gets chance to acquire the lock.
In my program Thread T1 spawns a new Thread T2 and calls join on that thread (i.e. T2.join ) and this newly spawned thread T2 calls join on T1 (i.e. T1.join). This is causing thread blocking. How this can be overcome.
My Program
public class PositiveNegativeNumberProducerV1 {
static Thread evenThread, oddThread;
public static void main(String[] args) {
oddThread = new Thread(new OddProducer(evenThread), "oddThread");
oddThread.start();
}
}
class EvenProducer implements Runnable {
Thread t;
EvenProducer(Thread t) {
this.t= t;
}
public void run() {
for(int i=1; i<=100; i++) {
if(i%2==0) {
System.out.println("i = "+i+":"+Thread.currentThread().getName());
try {
System.out.println("Now join will be called on "+t.getName()+" by thread "+Thread.currentThread().getName());
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
class OddProducer implements Runnable {
Thread t;
OddProducer(Thread t) {
this.t= t;
}
public void run() {
for(int i=1; i<=100; i++) {
if(i%2!=0) {
System.out.println("i = "+i+":"+Thread.currentThread().getName());
try {
if(t==null) {
t = new Thread(new EvenProducer(PositiveNegativeNumberProducerV1.oddThread), "evenThread");
t.start();
}
if(t.isAlive()) {
System.out.println("evenThread is alive and join will be called on "+t.getName()+" by thread "+Thread.currentThread().getName());
t.join();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
If you just want to synchronize the output: 1 2 3 4 ... then you should not use join (which waits for thread termination, i.e. leaving the run method). Consider to use the wait() and notify() pair on a semaphore object.
Object sema = new Object();
new Thread( new Runnable() {
#Override
public void run()
{
for ( int i = 1; i <= 100; i++ )
{
if ( i % 2 == 0 )
{
try
{
System.out.println( "Going to wait for the odd thread - "
+ Thread.currentThread().getName());
synchronized (sema)
{
sema.wait();
}
System.out.println( "i = " + i + ":" + Thread.currentThread().getName());
System.out.println( "Going to notify the odd thread - "
+ Thread.currentThread().getName());
synchronized (sema)
{
sema.notify();
}
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
}
}
}, "Even").start();
new Thread( new Runnable() {
#Override
public void run()
{
for ( int i = 1; i <= 100; i++ )
{
if ( i % 2 != 0 )
{
System.out.println( "i = " + i + ":" + Thread.currentThread().getName());
try
{
System.out.println( "Going to notify the even thread"
+ Thread.currentThread().getName());
synchronized (sema)
{
sema.notify();
}
System.out.println( "Going to wait for the even thread"
+ Thread.currentThread().getName());
synchronized (sema)
{
sema.wait();
}
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
}
}
}, "Odd").start();
I am new to multithreading, and get to know about the functionality of wait, notify and notifyAll. I want three threads to execute one after another and print alphabets from A to Z.
I have tried below code and it seems working also, but I doubt if this is the best possible way to tackle the problem. Is there any other way, I can make it more simple and better ? It seems some portion of my code is repeating.
package demo.threading;
class Flags {
boolean flagA = true;
boolean flagB = false;
boolean flagC = false;
}
class Container {
Flags flags = new Flags();
int charVal = (int) 'A';
void producer1() {
try {
while (charVal <= (int) 'Z') {
synchronized (this) {
if (!flags.flagA)
wait();
else {
System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
flags.flagA = false;
flags.flagB = true;
charVal++;
notifyAll();
Thread.sleep(1000);
}
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void producer2() {
try {
while (charVal <= (int) 'Z') {
synchronized (this) {
if (!flags.flagB)
wait();
else {
System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
flags.flagB = false;
flags.flagC = true;
charVal++;
notifyAll();
Thread.sleep(1000);
}
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void producer3() {
try {
while (charVal <= (int) 'Z') {
synchronized (this) {
if (!flags.flagC)
wait();
else {
System.out.println(Thread.currentThread().getName() + " Produced : " + (char) charVal);
flags.flagC = false;
flags.flagA = true;
charVal++;
notifyAll();
Thread.sleep(1000);
}
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
Container container = new Container();
Thread t1 = new Thread(() -> container.producer1(), "Thread 1");
Thread t2 = new Thread(() -> container.producer2(), "Thread 2");
Thread t3 = new Thread(() -> container.producer3(), "Thread 3");
t1.start();
t2.start();
t3.start();
}
}
Output should be :
Thread 1 Produced : A
Thread 2 Produced : B
Thread 3 Produced : C
Thread 1 Produced : D
Thread 2 Produced : E
Thread 3 Produced : F
As pointed out before, if you want to do this "one after another", you actually don't need multiple threads. However, you can achieve this by using a Semaphore:
int numberOfThreads = 3;
Semaphore semaphore = new Semaphore(1);
for (int i = 1; i <= numberOfThreads; i++) {
new Thread(() -> {
try {
semaphore.acquire();
for (char c : "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()) {
System.out.println(Thread.currentThread().getName()
+ " produced: " + c + ".");
}
} catch (InterruptedException e) {
// NOP
} finally {
semaphore.release();
}
}, "Thread " + i).start();
}
I recommend exploring java.util.concurrent which is available since Java 5. It's a great help to keep your concurrent code concise and simple compared with Java's low-level concurrency primitives such as wait and notify. If you're really interested in that topic, Brian Goetz's "Java Concurrency in Practice" is a must-read.
EDIT:
public class ConcurrentAlphabet {
private volatile Thread current;
public static void main(String[] args) {
new ConcurrentAlphabet().print(3,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray());
}
public void print(int numberOfThreads, char[] alphabet) {
Thread[] threads = new Thread[numberOfThreads];
for (int i = 1; i <= numberOfThreads; i++) {
int offset = i - 1;
threads[offset] = new Thread(() -> {
Thread me = Thread.currentThread();
Thread next = threads[(offset + 1) % numberOfThreads];
for (int index = offset; index < alphabet.length; index += numberOfThreads) {
synchronized (this) {
while (me != current) {
try {
wait();
} catch (InterruptedException e) { /* NOP */ }
}
System.out.println(me.getName() + " produced: " + alphabet[index] + ".");
current = next;
notifyAll();
}
}
}, "Thread " + i);
}
current = threads[0];
for (Thread t : threads) {
t.start();
}
}
}
package demo.thread;
public class ABCPuzzle {
private static class RunnableImpl implements Runnable {
private String nextThread;
private ExecServ execServ;
public RunnableImpl(ExecServ execServ, String nextThread) {
this.execServ = execServ;
this.nextThread = nextThread;
}
#Override
public void run() {
String threadName = Thread.currentThread().getName();
synchronized (execServ) {
try {
while (true) {
if (execServ.key > 'Z')
break;
if (threadName.equals(execServ.current)) {
System.out.println(threadName + " consuming " + execServ.key);
Thread.sleep(1000);
execServ.key++;
execServ.current = nextThread;
execServ.notifyAll();
} else
execServ.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class ExecServ {
private String current, next;
private char key = 'A';
}
public static void main(String[] args) {
ExecServ execServ = new ExecServ();
execServ.current = "t1";
Thread t1 = new Thread(new RunnableImpl(execServ, "t2"), "t1");
Thread t2 = new Thread(new RunnableImpl(execServ, "t3"), "t2");
Thread t3 = new Thread(new RunnableImpl(execServ, "t4"), "t3");
Thread t4 = new Thread(new RunnableImpl(execServ, "t1"), "t4");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Output :
t1 consuming A
t2 consuming B
t3 consuming C
t4 consuming D
t1 consuming E
t2 consuming F
t3 consuming G
t4 consuming H
t1 consuming I
t2 consuming J
Here I have two run methods which should synchronize each other.
Poller Class:
*/
public void run() {
int seqId = 0;
while(true) {
List<KpiMessage> list = null;
try{
if(!accumulator.isUsed){
try {
list = fullPoll(seqId);
if (!list.isEmpty()) {
seqId = list.get(0).getSequence();
accumulator.manageIngoing(list);
}
System.out.println("Updated");
wait();
} catch (Exception e1) {
e1.printStackTrace();
}
}
} catch (Exception e){
// TODO:
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
/**
* Method which defines polling of the database and also count the number of Queries
* #param lastSeq
* #return pojo col
* #throws Exception
*/
public List<KpiMessage> fullPoll(int lastSeq) throws Exception {
Statement st = dbConnection.createStatement();
System.out.println("Polling");
ResultSet rs = st.executeQuery("Select * from msg_new_to_bde where ACTION = 814 and
STATUS = 200 order by SEQ DESC");
List<KpiMessage> pojoCol = new ArrayList<KpiMessage>();
try {
while (rs.next()) {
KpiMessage filedClass = convertRecordsetToPojo(rs);
pojoCol.add(filedClass);
}
for (KpiMessage pojoClass : pojoCol) {
System.out.print(" " + pojoClass.getSequence());
System.out.print(" " + pojoClass.getTableName());
System.out.print(" " + pojoClass.getAction());
System.out.print(" " + pojoClass.getKeyInfo1());
System.out.print(" " + pojoClass.getKeyInfo2());
System.out.print(" "+ pojoClass.getStatus());
System.out.println(" " + pojoClass.getEntryTime());
}
} finally {
try {
st.close();
rs.close();
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
Processing and Updating Class:
public void run() {
while(true){
try {
while(!accumulator.isUsed)
{
try {
System.out.println("Waiting for new outgoingmessages");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Collection<KpiMessage> outgoingQueue = generate(accumulator.outgoingQueue);
accumulator.manageOutgoing(outgoingQueue, dbConnection);
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
}
I have a logical error:
The poller is polling not only for new messsage but also reads the DB again and again from the first.
Also Updates again and again.
How to solve this synchronization problem.
Alternatively you could use a BlockingQueue to transfer the data between threads.
See BlockingQueue for details.
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
private int i = 0;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i++);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
private int i = 0;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if ( i != null ) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue queue = new LinkedBlockingQueue();
Producer p = new Producer(queue);
Consumer c = new Consumer(queue);
Thread pt = new Thread(p);
Thread ct = new Thread(c);
// Start it all going.
pt.start();
ct.start();
// Close it down
pt.join();
ct.join();
}
You should synchronize or rather hold the lock or monitor for the object that you are calling wait() or notify() on.
Here is what will help you : wait() throwing IllegalArgumentException
synchronized(lockObject){
lockObject.wait(); //you should hold the lock to be able to call wait()
}