[Print alternatively using alternate Threads] - multithreading

I am trying to implement this:
First Thread prints 1,Second Thread prints 2,Third Thread prints 3,First Thread prints 4 and so on:
I did this and its working :
class Display implements Runnable
{
int threadId;
static int v=1;
static int turn=1;//init
static Object monitor=new Object();
Display(int id)
{
this.threadId=id;
}
public void run() {// TODO Auto-generated method stub
print();
}
private void print() {
// TODO Auto-generated method stub
while(v<100)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
synchronized(monitor)
{
if(threadId==1)
{
if(turn!=1)
{
try {
monitor.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
System.out.println(threadId + ":"+v);
v++;
turn=2;
monitor.notifyAll();
}
}
else if(threadId==2)
{
if(turn!=2)
{
try {
monitor.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
System.out.println(threadId+":"+v);
v++;
turn=3;
monitor.notifyAll();
}
}
else
{
if(turn!=3)
{
try {
monitor.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
System.out.println(threadId+":"+v);
v++;
turn=1;
monitor.notifyAll();
}
}
}
}
}
}
public class Print {
public static void main(String[] ar)
{
Thread t1= new Thread(new Display(1));
Thread t2= new Thread(new Display(2));
Thread t3= new Thread(new Display(3));
t1.start();
t2.start();
t3.start();
}
}
Output is like this:
1:1
2:2
3:3
1:4
2:5
It achieves the purpose but if I am having two more Threads to print alternatively,then I have to use more If conditions.
Can Anyone suggest to write this code in a better form to achieve that task in a more clean way so that it is extendable if more Threads are added.

You will need the highest Id given to your threads. After this, you can simplify your code using the modulo operator.
class Display implements Runnable {
int threadId;
static int v = 1;
static int higehstId = 0;
static Object monitor = new Object();
Display(int id) {
this.threadId = id;
}
public void run() {
print();
}
private void print() {
while (v < 100) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (monitor) {
if ((v - 1) % higehstId == threadId - 1) {
System.out.println(threadId + ":" + v);
v++;
monitor.notifyAll();
} else {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] ar) {
Thread t1 = new Thread(new Display(1));
Thread t2 = new Thread(new Display(2));
Thread t3 = new Thread(new Display(3));
Thread t4 = new Thread(new Display(4));
Thread t5 = new Thread(new Display(5));
Display.higehstId = 5;
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
If you initialize v to 0 and start numbering the Threads from 0, you could simplify the if statement to this:
if(v % highestId == threadId)

Related

Printing even and odd number by two thread

I am trying to print even and odd number using two different thread but It is throwing IllegalMonitorStateException .Kindly suggest me what am I doing wrong .
package com.rishi.threading;
public class MyThread {
public static class EvenThread extends Thread {
Boolean evenFlag;
Integer sharedCount;
public EvenThread(Boolean flag, Integer count) {
this.evenFlag = flag;
this.sharedCount = count;
}
public void run() {
printEven();
}
private void printEven() {
for (int i = 0; i < 10; i++) {
synchronized (evenFlag) {
if (!evenFlag) {
try {
evenFlag.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
evenFlag = false;
System.out.println("even thread :" + sharedCount++);
notifyAll();
}
}
}
}
public static class OddThread extends Thread {
Boolean evenflag;
Integer sharedCount;
public OddThread(Boolean flag, Integer count) {
this.evenflag = flag;
this.sharedCount = count;
}
public void run() {
printOdd();
}
private void printOdd() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
synchronized (evenflag) {
if (evenflag) {
try {
evenflag.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
evenflag = true;
System.out.println("odd thread :" + sharedCount++);
notifyAll();
}
}
}
}
public static void main(String[] args) {
Boolean evenFlag = new Boolean(true);
Integer sharedCount = new Integer(0);
EvenThread thread1 = new EvenThread(evenFlag, sharedCount);
thread1.setName("evenThread");
OddThread thread2 = new OddThread(evenFlag, sharedCount);
thread2.setName("oddthread");
thread1.start();
thread2.start();
}
}
I created two thread "EvenThread" and "OddThread".
Both the thread shares two common member variable ie evenFlag and sharedCount.
evenFlag -> just a flag which is set as true when sharedCount is even and set as false when shareDcount is set to odd number.
So both the thread is trying to get lock of evenFlag to control the printing of sharedCount.

zk LongUIOperation Executions.deactivate null pointer exception

I'm using LongUIOperation custom implementation, but, sometimes, on
Executions.deactivate(getNativeDesktop());
I receive messagebox on screen and:
dic 11, 2017 11:09:42 AM org.zkoss.zk.ui.impl.UiEngineImpl handleError
GRAVE: java.lang.NullPointerException at
org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1528)
at
org.apache.catalina.connector.Request.setAttribute(Request.java:1514)
at
org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:540)
at
org.zkoss.zk.ui.http.ExecutionImpl.setAttribute(ExecutionImpl.java:497)
at org.zkoss.zk.ui.impl.Utils.getComponentInfos(Utils.java:120) at
org.zkoss.zk.ui.impl.Utils.setComponentInfo(Utils.java:129) at
org.zkoss.zk.ui.impl.AbstractUiFactory.newComponent(AbstractUiFactory.java:137)
at
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:919)
at
org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:889)
at
org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:776)
at org.zkoss.zk.ui.impl.UiEngineImpl.access$800(UiEngineImpl.java:128)
at
org.zkoss.zk.ui.impl.UiEngineImpl$TemplateImpl.create(UiEngineImpl.java:2318)
at
org.zkoss.bind.impl.BindListitemRenderer.render(BindListitemRenderer.java:79)
at org.zkoss.zul.Listbox$Renderer.render(Listbox.java:2769) at
org.zkoss.zul.Listbox.doInitRenderer(Listbox.java:2584) at
org.zkoss.zul.Listbox.onInitRender(Listbox.java:2537) at
sun.reflect.GeneratedMethodAccessor2366.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) at
org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3146)
at
org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3077)
at
org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138)
at
org.zkoss.zk.ui.impl.UiEngineImpl.processEvent(UiEngineImpl.java:1846)
at org.zkoss.zk.ui.impl.UiEngineImpl.process(UiEngineImpl.java:1618)
at org.zkoss.zk.ui.impl.UiEngineImpl.endUpdate(UiEngineImpl.java:1222)
at
org.zkoss.zkex.ui.comet.CometServerPush.deactivate(CometServerPush.java:522)
at
org.zkoss.zk.ui.impl.DesktopImpl.deactivateServerPush(DesktopImpl.java:1596)
at org.zkoss.zk.ui.Executions.deactivate(Executions.java:1011) at
com.ims.web.ui.GenericViewModel.deactivateNativeDesktop(GenericViewModel.java:193)
at
com.ims.web.zk.ui.DesktopVMLongUIOperation.run(DesktopVMLongUIOperation.java:186)
at java.lang.Thread.run(Unknown Source)
Use case example:
#Command
#Override
public void editBaseItem() throws Exception {
super.editBaseItem();
if(selectedBaseItem.getOid() == null){
initNewItem();
}
final String sessionID = getSessionID();
final StaffDailyAvailabilityVM instanceVM = this;
new DesktopVMLongUIOperation(this,win,Labels.getLabel("def.msg.refreshdata","Refresh data...")) {
#Override
protected void execute() throws InterruptedException {
try {
StaffDailyAvailabilityManager.evaluateStaffDailyAvailabilitySynch(selectedBaseItem, sessionID);
} catch (Exception e) {
logger.error(e,e);
}
}
protected void onCleanup() {
try {
//refresh clock time list
selectedBaseItem.getLastStaffDailyTimestampDTO();
if(selectedBaseItem.isErrorDetected()){
selectedBaseItem.setCertified(false);
}
BindUtils.postNotifyChange(null, null, instanceVM.getSelectedBaseItem(),"lastStaffDailyTimestampDTO");
BindUtils.postNotifyChange(null, null, instanceVM, "selectedBaseItem");
} catch (Exception e) {
logger.error(e,e);
}
};
}.start();
}
Here the code:
public abstract class DesktopVMLongUIOperation implements Runnable {
protected static final Logger logger = Logger.getLogger(DesktopVMLongUIOperation.class);
private Thread thread;
private AtomicBoolean cancelled = new AtomicBoolean(false);
private Window win;
private GenericViewModel genericViewModel;
public DesktopVMLongUIOperation(GenericViewModel genericViewModel){
this(genericViewModel,null,"");
}
public DesktopVMLongUIOperation(GenericViewModel genericViewModel, Window win, String busyMsg){
this.win = win;
this.genericViewModel = genericViewModel;
try {
this.genericViewModel.enableServerPush(null);
if(win != null){
Clients.showBusy(win,busyMsg);
}
} catch (Exception e) {
logger.error(e,e);
}
}
/**
* asynchronous callback for your long operation code
* #throws InterruptedException
*/
protected abstract void execute() throws InterruptedException;
/**
* optional callback method when the task has completed successfully
*/
protected void onFinish() {};
/**
* optional callback method when the task has been cancelled or was interrupted otherwise
*/
protected void onCancel() {};
/**
* optional callback method when the task has completed with an uncaught RuntimeException
* #param exception
*/
protected void onException(RuntimeException exception) {
logger.error(exception,exception);
};
/**
* optional callback method when the task has completed (always called)
*/
protected void onCleanup() {};
/**
* set the cancelled flag and try to interrupt the thread
*/
public final void cancel() {
try {
cancelled.set(true);
if(thread != null){
thread.interrupt();
}
} catch (Throwable e) {
logger.error(e,e);
}
}
/**
* check the cancelled flag
* #return
*/
public final boolean isCancelled() {
return cancelled.get();
}
/**
* Checks if the task thread has been interrupted. Use this to check whether or not to exit a busy operation in case.
* #throws InterruptedException when the current task has been cancelled/interrupted
*/
protected final void checkCancelled() throws InterruptedException {
try {
if(Thread.currentThread() != this.thread) {
throw new IllegalStateException("this method can only be called in the worker thread (i.e. during execute)");
}
boolean interrupted = Thread.interrupted();
if(interrupted || cancelled.get()) {
cancelled.set(true);
throw new InterruptedException();
}
} catch (Throwable e) {
logger.error(e,e);
}
}
/**
* launch the long operation
*/
public final void start() {
try {
thread = new Thread(this);
thread.start();
} catch (Throwable e) {
logger.error(e,e);
}
}
#Override
public final void run() {
try {
try {
checkCancelled(); //avoid unnecessary execution
execute();
checkCancelled(); //final cancelled check before calling onFinish
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: RUN");
onFinish();
} catch (InterruptedException e) {
try {
cancelled.set(true);
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: INTERRUPT");
onCancel();
} catch (InterruptedException e1) {
throw new RuntimeException("interrupted onCancel handling", e1);
} catch (Exception e1) {
logger.error(e1,e1);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("DEACTIVATE: INTERRUPT");
} catch (Exception e1) {
logger.error(e1,e1);
}
}
} catch (RuntimeException rte) {
try {
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: EXCEPTION");
onException(rte);
} catch (InterruptedException e1) {
throw new RuntimeException("interrupted onException handling", e1);
} catch (Exception e) {
logger.error(e,e);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("ACTIVATE: EXCEPTION");
} catch (Exception e) {
logger.error(e,e);
}
}
throw rte;
} catch (Exception e) {
logger.error(e,e);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("DEACTIVATE: RUN");
} catch (Exception e) {
logger.error(e,e);
}
}
} finally {
try {
genericViewModel.activateNativeDesktop();
logger.error("ACTIVATE: CLEANUP");
try {
if(win != null){
Clients.clearBusy(win);
}
} catch (Exception e) {
logger.error(e,e);
}
onCleanup();
} catch (InterruptedException e1) {
throw new RuntimeException("interrupted onCleanup handling", e1);
} catch (Exception e1) {
logger.error(e1,e1);
} finally {
try {
genericViewModel.deactivateNativeDesktop();
logger.error("DEACTIVATE: CLEANUP");
} catch (Exception e) {
logger.error(e,e);
}
}
}
}
}
And activate deactivate code from genericViewModel:
... ... public GenericViewModel(){ nativeDesktop = Executions.getCurrent().getDesktop(); }
... ...
public GenericViewModel(){
nativeDesktop = Executions.getCurrent().getDesktop();
}
public boolean activateNativeDesktop() throws Exception{
boolean res = false;
if(getNativeDesktop() != null && getNativeDesktop().isAlive()){
try {
Executions.activate(getNativeDesktop());
res = true;
} catch (Throwable e) {
logger.error(e,e);
throw(e);
}
}else{
throw new Exception("ZK native Desktop is null");
}
return res;
}
public boolean deactivateNativeDesktop() throws Exception{
boolean res = false;
if(getNativeDesktop() != null && getNativeDesktop().isAlive()){
try {
Executions.deactivate(getNativeDesktop());
res = true;
} catch (Throwable e) {
logger.error(e,e);
throw(e);
}
}else{
throw new Exception("ZK native Desktop is null");
}
return res;
}

PingPong Program Java Multithreading

I am trying to learn basic concept of Multi Threading.
Why my ping pong program prints only Ping0 & Pong0, Why notify() does not start the Ping Thread which is in Wait state?
public class PingPong implements Runnable {
String word;
public PingPong(String word) {
this.word = word;
}
public void run() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(word + i);
try {
wait();
notifyAll();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
public static void main(String[] args) {
Runnable p1 = new PingPong("ping");
Thread t1 = new Thread(p1);
t1.start();
Runnable p2 = new PingPong("pong");
Thread t2 = new Thread(p2);
t2.start();
}
}
Output
ping0
pong0
I tried removing wait() and it's printing ping pong till the end of loop. but is this guaranteed that it will print in sequence?
Why wait() followed by notify() does not ask the ping1 thread to start execution?
If you see the jstack, you can see thread-0 and thread-1 are waiting for different lock. That's because your p1 and p2 are different objects, so when you use synchronized (this), they are not competing for the same lock, so notify this way won't work. try use another object as the lock.
wait need to run after notify. As when both threads go into waiting stat, no other threads can notify them.
try this code:
String word;
Object a;
public PingPong(String word, Object a) {
this.word = word;
this.a = a;
}
public void run() {
synchronized (a) {
for (int i = 0; i < 10; i++) {
System.out.println(word + i);
try {
a.notifyAll();
a.wait();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Object a = new Object();
Runnable p1 = new PingPong("ping", a);
Thread t1 = new Thread(p1);
t1.start();
Runnable p2 = new PingPong("pong", a);
Thread t2 = new Thread(p2);
t2.start();
}
Here is a similar solution using Thread Pool Executors:
public class PingPong implements Runnable {
String word;
Lock lock;
public PingPong(String word, Lock lock) {
this.word = word;
this.lock = lock;
}
#Override
public void run() {
while(true){
System.out.println("Received : " + word);
lock.notifyAll();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ExecutorService ex = Executors.newFixedThreadPool(2);
Lock lock = new ReentrantLock();
while(true){
ex.submit(new PingPong("ping", lock));
ex.submit(new PingPong("pong", lock));
}
}
}
Below solution based on:
Java internal API
order of execution
public class Test {
public static void main(String[] args) {
SynchronousQueue<String> queue = new SynchronousQueue<>();
Thread ping = new Thread(new Task(queue, "ping", "ping"));
ping.setName("ping thread");
ping.start();
Thread pong = new Thread(new Task(queue, "pong", "ping"));
pong.setName("pong thread");
pong.start();
}
private static class Task implements Runnable {
private SynchronousQueue<String> queue;
private String command;
private String step;
Task(SynchronousQueue<String> queue, String command, String step) {
this.queue = queue;
this.command = command;
this.step = step;
}
#Override
public void run() {
try {
if (command.equals(step)) {
doCommandAndWaitRepeatedly();
} else {
waitAndDoCommandRepeatedly();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void doCommandAndWaitRepeatedly() throws InterruptedException {
while (true) {
queue.offer(command, 1, TimeUnit.SECONDS);
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ":" + queue.poll(1, TimeUnit.SECONDS));
}
}
private void waitAndDoCommandRepeatedly() throws InterruptedException {
while (true) {
System.out.println(Thread.currentThread().getName() + ":" + queue.poll(1, TimeUnit.SECONDS));
Thread.sleep(500);
queue.offer(command, 1, TimeUnit.SECONDS);
}
}
}
}
class Ping extends Thread
{
public void run()
{
for(int i=1;i<=5;i++)
{
System.out.println("PING");
try{
sleep(2000);
} catch(Exception e){}
}
}
}
class Pong extends Thread
{
public void run()
{
for (int i=1;i<=5;i++)
{
System.out.println("PONG");
try{
sleep(2000);
} catch(Exception e){}
}
}
}
public class PingPong
{
public static void main(String... args) throws Exception
{
Ping p1=new Ping();
Pong p2=new Pong();
p1.start();
Thread.sleep(1000); //super important for proper sequence
p2.start();
p1.join();
}
}

JavaFX pie Charts ObservableList (Chart GUI update not accurate when passed on Thread)

please help me guys..
my observablelist was updated successfully by background Thread.
but my GUI Update is not accurate.
addPiechart1 to HBOX
addPieChart2 to HBOX
observablelist1= getobservablelist from piechart1
observablelist2= getobservablelist from piechart2
pass observablelist1 to Thread
pass observablelist2 to Thread
ex
on the process i call
animatePie(observablelist1,value1);
animatePie(observablelist2,value2);
public void animatePie(ObservableList<PieChart.Data> obs,int[] value){
ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() {
#Override public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
return thread;
}
});
pieAddToQueue add = new pieAddToQueue(obs,value);
//add.run();
executor.execute(add);
}
private class pieAddToQueue implements Runnable {
ObservableList<PieChart.Data> observableData;
int[] value;
int loop;
public pieAddToQueue(ObservableList<PieChart.Data> obs,int[] value){
observableData=obs;
this.value=value;
loop=0;
}
#Override
public void run() {
for(int i=0;i<value.length;i++){
observableData.get(i).setPieValue(value[i]);
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(MISInfoBoardBottom.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
You cannot update the UI on a background thread, so you must wrap the calls that change the UI with a Platform.runLater(...):
private class pieAddToQueue implements Runnable {
ObservableList<PieChart.Data> observableData;
int[] value;
int loop;
public pieAddToQueue(ObservableList<PieChart.Data> obs,int[] value){
observableData=obs;
this.value=value;
loop=0;
}
#Override
public void run() {
for(int i=0;i<value.length;i++){
PieChart.Data pieChartData = observableData.get(i);
int v = value[i] ;
Platform.runLater(() ->
pieChartData.setPieValue(v));
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(MISInfoBoardBottom.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}

Thread synchronization with multiple objects

I have been facing this problem for many days, Please help me out. I am implementing producer-consumer example using thread synchronization. I have made some twist in this traditional program. Instead of using only one queue object, i have used two Queue objects. But program is not working.. (PS- I know i can make this program work by using only one object of queue, But what if i want to use two queue objects ?? )
class Queue {
static int value;
static boolean valueSet = false;
public static final Object obj;
static {
obj = new Object();
}
void push() {
synchronized(Queue.obj) {
while( Queue.valueSet ) {
try {
Thread.sleep(1000);
}catch(Exception e) {}
}
System.out.print("\n\n Push:- " + (++(Queue.value)));
Queue.valueSet = true;
return;
}
}
void pop() {
synchronized(Queue.obj) {
while(!(Queue.valueSet)) {
try {
Thread.sleep(1000);
}catch(Exception e) {}
}
System.out.print("\n\n Pop:- " + Queue.value);
Queue.valueSet = false;
return;
}
}
}
class Producer implements Runnable {
Queue Q;
Thread P;
Producer(Queue Q) {
this.Q = Q;
P = new Thread(this);
P.start();
}
public void run() {
while(true) {
Q.push();
}
}
}
class Consumer implements Runnable {
Queue Q;
Thread C;
Consumer(Queue Q) {
this.Q = Q;
C = new Thread(this);
C.start();
}
public void run() {
while(true) {
Q.pop();
}
}
}
public class TestQueue {
public static void main(String[] args) {
Queue Q1 = new Queue();
Queue Q2 = new Queue();
Object obj = new Object();
Producer p = new Producer(Q1);
Consumer c = new Consumer(Q2);
}
}
I got the answer. My misconception was wait,notify and notifyall methods are of thread class. So i was invoking them on thread object.
Solution is to just invoke wait and notify method on shared static object other than thread.
Answer:-
class Queue {
static int value;
static boolean valueSet = false;
public static final Object obj;
static {
obj = new Object();
}
void push() {
synchronized(Queue.obj) {
while( Queue.valueSet ) {
try {
Queue.obj.wait();
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.print("\n\n Push:- " + (++(Queue.value)));
Queue.valueSet = true;
Queue.obj.notify();
}
}
void pop() {
synchronized(Queue.obj) {
while(!(Queue.valueSet)) {
try {
Queue.obj.wait();
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.print("\n\n Pop:- " + Queue.value);
Queue.valueSet = false;
Queue.obj.notify();
}
}
}
class Producer implements Runnable {
Queue Q;
Thread P;
Producer(Queue Q) {
this.Q = Q;
P = new Thread(this);
P.start();
}
public void run() {
while(true) {
Q.push();
}
}
}
class Consumer implements Runnable {
Queue Q;
Thread C;
Consumer(Queue Q) {
this.Q = Q;
C = new Thread(this);
C.start();
}
public void run() {
while(true) {
Q.pop();
}
}
}
public class TestQueue {
public static void main(String[] args) {
Queue Q1 = new Queue();
Queue Q2 = new Queue();
Producer p = new Producer(Q1);
Consumer c = new Consumer(Q2);
}
}

Resources