Dining savages using monitors [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Im trying to understand how implement Dining Savages using monitors. I have three classes, and im using the kitchen class to act as the monitor for when the pot is empty or not.
For some reason i keep getting a null pointer exception at thread two in my example below.
class Kitchen {
Kitchen k;
int c;
boolean empty;
Cook chef;
Kitchen() {
this.c = 0;
this.empty = true;
chef = new Cook(k);
}
synchronized void putServingsInPot(int servings) {
if (empty) {
this.c = servings;
}
empty = false;
notify();
}
synchronized void getServingsFromPot() {
while (empty) {
try {
System.out.println("Bout to wait");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
System.out.println("In Catch");
e.printStackTrace();
}if (c == 0) {
empty = true;
chef.run();
}else if(c > 0 && empty == false){
c--;
}
}
}
}
class Savage extends Thread {
Kitchen k;
Savage(Kitchen k) {
this.k = k;
}
public void run() {
while (true) {
k.getServingsFromPot();
try {Thread.sleep(500); // eat
} catch (Exception e) { return;}
}
}
}
class Cook extends Thread {
Kitchen k;
Cook(Kitchen k) {
this.k = k;
}
public void run() {
while (true) {
try {Thread.sleep(500); // sleep
} catch (Exception e) {return;}
k.putServingsInPot(10); // 10 servings
}
}
}
public class main {
public static void main(String Args[]) {
// Kitchen testing
Kitchen k = new Kitchen();
Cook c = new Cook(k);
c.start();
Savage sc[] = new Savage[9];
for (int i = 0; i < 9; i++) {
sc[i] = new Savage(k);
sc[i].start();
}
try {
Thread.sleep(5000);
} catch (Exception e) {
}
for (int i = 0; i < 9; i++) {
sc[i].interrupt();
}
c.interrupt();
System.out.println("Done\n");
}
}
Is it possible to synchronized these events without using a semaphore within the monitor ?

Look at the definition of Kitchen:
class Kitchen {
Kitchen k; // Here the kitchen is null
int c;
boolean empty;
Cook chef;
Kitchen() {
this.c = 0;
this.empty = true;
chef = new Cook(k); // here you give a null object to the cook constructor
}
you are giving a null object to the Cook constructor. Maybe you want to give yourself to the Cook object:
class Kitchen {
//Kitchen k; I don't think you will need it anymore, you can delete this line
int c;
boolean empty;
Cook chef;
Kitchen() {
this.c = 0;
this.empty = true;
chef = new Cook(this); // give yourself to the Cook
}

Related

Confused about how to use exchanger in java

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();
}

Dinning philosophers algorithm deadlock [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have written algorithm to solved dinning philosophers problem. But its giving stackoverflow exception.Can any one help me with the same. To over some the issue. It is a dinning philosopher problem using multi threading. Where I am using ArrayList to store chopsticks and plates.
`
-----------
package com.intech.DiningPhilosopherProblem;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.annotation.processing.Processor;
public class MyPhilosophers {
/**
* #param args
*/
static int noOfP = ((Runtime.getRuntime().availableProcessors() * 2) + (1));
// Runtime.getRuntime().availableProcessors();
public static void main(String[] args) throws InterruptedException {
MyPhilosophersChopstick myPs = new MyPhilosophersChopstick(noOfP);
ExecutorService execserv = Executors.newFixedThreadPool(5);
for (int i = 0; i < 500; i++) {
Thread.sleep(200);
execserv.execute(myPs);
}
// execserv.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!execserv.awaitTermination(600, TimeUnit.SECONDS)) {
execserv.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!execserv.awaitTermination(600, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
}
catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
execserv.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
`
package com.intech.DiningPhilosopherProblem;
public class MyPhilosophersChopstick implements Runnable {
volatile int eatingturns =0;
volatile int allowedeatingturns =200;
volatile int noOfChopsticks=0;
volatile int[] arrayChopsticks;
volatile int i=0;
public MyPhilosophersChopstick(int chopsticks)
{
arrayChopsticks=new int[chopsticks];
this.noOfChopsticks=chopsticks;
for (int i = 0; i < noOfChopsticks; i++)
{
arrayChopsticks[i]=0;
}
System.out.println("noOfChopsticks"+noOfChopsticks);
System.out.println("arrayChopsticks.length"+arrayChopsticks.length);
}
public void run()
{ System.out.println("run count"+ i++);
while(eatingturns<allowedeatingturns)
{
String s=Thread.currentThread().getName();
char c=s.charAt(s.length()-1); //c = which thread thread no 1, thread no 2, thread no 3, thread no 4. It denotes to which philosopher in char
int j=(int)c; //j = which thread thread no 1, thread no 2, thread no 3, thread no 4. It denotes to which philosopher in int where 0=49 , 1=50.... and so on
System.out.println("j"+j);
if(c>noOfChopsticks)
System.out.println("c"+c);
j=j-49; //converting char in to int digits as value for 0=49, 1=50.... and so on
System.out.println("j"+j);
System.out.println( Thread.currentThread().getName()+"Thinking-------------"+j);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
hungary(j);
}
}
public void hungary(int i)
{
//System.out.println( Thread.currentThread().getName()+"Inside hungary()-------------"+i);
//else nothing
boolean a=eat(i);
if(a==true)
System.out.println(Thread.currentThread().getName()+"Eating-------------"+i+""+arrayChopsticks[i]);
synchronized (this){
eatingturns++;
}
a=doneEating(i);
}
private boolean eat(int i) {
// TODO Auto-generated method stub
// System.out.println(
// Thread.currentThread().getName()+"Inside eat()-------------"+i);
boolean a;
boolean b;
if (i == 0) {
synchronized (this) {
if ((a = pickchopstickRight(i))
&& (b = pickchopstickLeft(arrayChopsticks.length - 1))) {
return true;
}
keepChopstickRight(i); // if right chopstick not available
return false;
}
} else {
if ((a = pickchopstickRight(i)) && (b = pickchopstickLeft(i - 1))) {
return true;
}
keepChopstickRight(i); // if right chopstick not available
return false;
}
}
private boolean doneEating(int i) {
// TODO Auto-generated method stub
//System.out.println( Thread.currentThread().getName()+"Inside wantToThink()-------------"+i);
boolean a;
boolean b;
if(i==0){
//synchronized (this)
{
a=keepChopstickLeft(arrayChopsticks.length-1);
b=keepChopstickRight(i);
}
}
else
{
a=keepChopstickLeft(i-1);
b=keepChopstickRight(i); //pandey
}
if(a&&b)
{
return true;
}
return false;
}
private boolean keepChopstickLeft(int i) {
//System.out.println( Thread.currentThread().getName()+"INSIDE keepchopstick Left -------------"+i);
if(arrayChopsticks[i]==1)
{
System.out.println( Thread.currentThread().getName()+"Keeping down Left chopstick -------------"+i+""+arrayChopsticks[i]);
arrayChopsticks[i]=0;
return true;
}
return false;
}
private boolean keepChopstickRight(int i)
{
System.out.println( Thread.currentThread().getName()+"INSIDE keepchopstick Right -------------"+i+""+arrayChopsticks[i]);
if(arrayChopsticks[i]==1)
{
System.out.println( Thread.currentThread().getName()+"Keeping down Right chopstick -------------"+i+""+arrayChopsticks[i]);
arrayChopsticks[i]=0;
run(); //goest to run
}
return false;
}
private boolean pickchopstickLeft(int i)
{
//System.out.println( Thread.currentThread().getName()+"INSIDE pickchopstickLEFT -------------"+i);
if(arrayChopsticks[i]==0)
{
System.out.println( Thread.currentThread().getName()+"picking up chopstick Left -------------"+i+""+arrayChopsticks[i]);
arrayChopsticks[i]=1;
return true;
}
return false;
}
private boolean pickchopstickRight(int i) {
//System.out.println( Thread.currentThread().getName()+"INSIDE pickchopstickRight -------------"+i);
if(arrayChopsticks[i]==0)
{
System.out.println( Thread.currentThread().getName()+"picking up chopstick Right -------------"+i+""+arrayChopsticks[i]);
arrayChopsticks[i]=1;
return true;
}
return false;
}
}
it might be beauase of there is a memory leak in the program or you will have to increase the heap and stack size using -xMx -Xms

Producer Consumer in java multithreaded

I'm trying to implement a Producer Consumer problem in java. I'm using a circular buffer (circular array) to for the Producer to insert items into the buffer. Following is my code:
import java.util.*;
import java.io.*;
public class Buffer
{
String a[];
int front, rear;
public Buffer(int size)
{
a = new String[size];
front = rear = -1;
}
public boolean insert(String dataitem)
{
int p;
p = (rear+1) % a.length;
if(p==front)
{
System.out.println("Buffer full");
return false;
}
else
{ rear = p;
a[rear] = dataitem;
if(front == -1)
front = 0;
return true;
}
}
public boolean empty()
{
if(front == -1)
return true;
else
return false;
}
public String delete()
{
String result = a[front];
if(front == rear)
front = rear = -1;
else
front = (front +1)%a.length;
return result;
}
public void display()
{
if(front == -1)
System.out.println("Buffer empty");
else
{
System.out.println("Buffer elements are:");
int i= front;
while(i!= rear)
{
System.out.println(a[i]);
i = (i+1)%a.length;
}
System.out.println(a[i]);
}
}
public static void main(String[] args)
{
int size = Integer.parseInt(args[0]);
Buffer b = new Buffer(size);
int ch;
String dataitem, msg;
Thread prod = new Thread(new Producer(b, size));
Thread cons = new Thread(new Consumer(b, size));
prod.start();
cons.start();
}
}
class Producer extends Thread
{
Buffer b;
int size;
public Producer(Buffer b, int size)
{
this.b = b;
this.size = size;
}
public void run()
{
while(true)
{
synchronized(b)
{
for(int i = 1; i <= size; i++)
{
try
{ String dataitem = Thread.currentThread().getId()+"_"+i;
boolean bool = b.insert(dataitem);
//b.notifyAll();
if(bool)
System.out.println("Successfully inserted "+dataitem);
b.notifyAll();
Thread.sleep(2000);
}
catch(Exception e)
{ e.printStackTrace();
}
}
}
}
}
}
class Consumer extends Thread
{
Buffer b;
int size;
public Consumer(Buffer b, int size)
{
this.b = b;
this.size = size;
}
public void run()
{
while(b.empty())
{
synchronized(b)
{
try
{
System.out.println("Buffer empty");
b.wait();
}
catch(Exception e)
{ e.printStackTrace();
}
}
}
synchronized(b)
{
b.notifyAll();
String dataitem = b.delete();
System.out.println("Removed "+dataitem);
}
}
}
The producer is inserting dataitems into the buffer successfully. But they aren't being consumed by the consumer.
I get the following output when I execute the program.
Successfully inserted 11_1
Successfully inserted 11_2
Buffer full
Buffer full
Buffer full
Buffer full
Buffer full
Buffer full
My question is how do I get the consumer to consume items from the buffer?
The major problem is that the synchronized block in your Producer is too wide. It is never letting the Consumer acquire the lock
Start by narrowing the scope, for example...
while (true) {
for (int i = 1; i <= size; i++) {
try {
String dataitem = Thread.currentThread().getId() + "_" + i;
boolean bool = b.insert(dataitem);
//b.notifyAll();
if (bool) {
System.out.println("Successfully inserted " + dataitem);
}
synchronized (b) {
b.notifyAll();
}
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
You may also consider synchronizing the ing insert and delete methods themselves. I personally would be tempted to use a internal lock, but you could simply synchronize the methods themselves, for example...
public synchronized boolean insert(String dataitem) {...}
public synchronized String delete() {...}
As it stands, your Consumer will only ever read a single value from the buffer, but I'll let you figure that one out ;)
As a side note, I might put the wait and notify functionality directly within the Buffer, so that whenever you try and delete a value, it will wait, within the delete method for the Buffer to be not empty and allow the insert method to make the notifications itself...but that's me ;)
Equally, I might consider blocking the insert method until there is more room, but that will come down to how you want to implement it :P
Updated
Very basically, this will start giving the results you are looking for...
public class ProducerConsumer {
public static void main(String[] args) {
new ProducerConsumer();
}
public ProducerConsumer() {
int size = 5;
Buffer b = new Buffer(size);
Thread prod = new Thread(new Producer(b, size));
Thread cons = new Thread(new Consumer(b, size));
prod.start();
cons.start();
}
public class Buffer {
String a[];
int front, rear;
public Buffer(int size) {
a = new String[size];
front = rear = -1;
}
public synchronized boolean insert(String dataitem) {
int p;
p = (rear + 1) % a.length;
if (p == front) {
System.out.println("Buffer full");
return false;
} else {
rear = p;
a[rear] = dataitem;
if (front == -1) {
front = 0;
}
return true;
}
}
public boolean empty() {
return front == -1;
}
public synchronized String delete() {
String result = a[front];
if (front == rear) {
front = rear = -1;
} else {
front = (front + 1) % a.length;
}
return result;
}
public void display() {
if (front == -1) {
System.out.println("Buffer empty");
} else {
System.out.println("Buffer elements are:");
int i = front;
while (i != rear) {
System.out.println(a[i]);
i = (i + 1) % a.length;
}
System.out.println(a[i]);
}
}
}
class Producer extends Thread {
Buffer b;
int size;
public Producer(Buffer b, int size) {
this.b = b;
this.size = size;
}
public void run() {
int i = 0;
while (true) {
try {
String dataitem = Thread.currentThread().getId() + "_" + ++i;
boolean bool = b.insert(dataitem);
if (bool) {
System.out.println("Successfully inserted " + dataitem);
}
synchronized (b) {
b.notifyAll();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
Buffer b;
int size;
public Consumer(Buffer b, int size) {
this.b = b;
this.size = size;
}
public void run() {
while (true) {
while (b.empty()) {
synchronized (b) {
try {
System.out.println("Buffer empty");
b.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
String dataitem = null;
synchronized (b) {
dataitem = b.delete();
}
System.out.println("Removed " + dataitem);
}
}
}
}

Print RED BLUE GREEN in order using System.out.print

public class CyclicBar {
private final static CyclicBarrier cb = new CyclicBarrier(3,
new Runnable() {
#Override
public void run() {
System.out.println("\n-------------");
}
});
public static void main(String[] args) {
final class ColouredRunnable implements Runnable {
private int i;
public ColouredRunnable(int j) {
this.i = j;
}
#Override
public void run() {
final String name = Thread.currentThread().getName();
while (true) {
cyclicAwait();
for (int i = 0; i < name.length(); i++) {
sleep();
// System.out.print("" + name.charAt(i) + this.i + " ");
System.out.print("" + name.charAt(i) + " ");
}
}
}
}
;
int i = 0;
new Thread(new ColouredRunnable(i++), "RED").start();
new Thread(new ColouredRunnable(i++), "BLUE").start();
new Thread(new ColouredRunnable(i++), "GREEN").start();
}
private static int cyclicAwait() {
try {
return cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return -1;
}
private static void sleep() {
try {
Thread.sleep(ThreadLocalRandom.current().nextLong(200, 600));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Above code currently prints
-------------
G R B R E L E E D U E N
-------------
B R G E R L U E D E E N
-------------
R G B E L R E U D E E N
-------------
R G B E R L U E D E E N
-------------
B R G E L D R U E E E N
-------------
How to alter above code and add proper barrier at appropriate location to produce following output
-------------
R E D B L U E G R E E N
-------------
R E D B L U E G R E E N
-------------
R E D B L U E G R E E N
Constraints
Must use one of modern java concurrent higher level Objects
Should not use implicit locking synchronised wait notify
must print individual characters using System.out.print()
use 3 thread with each thread must print its name (colour)
It should be printed in the order RED BLUE GREEN
public class TestSynMain {
private final static AbstractQueuedSynchronizer cb = new TestSynchronizer(6);
public static void main(String[] args) {
final class ColouredRunnable implements Runnable {
private String color;
public ColouredRunnable(String color) {
this.color = color;
}
#Override
public void run() {
while (true) {
try {
boolean result = false;
do{
result = cb.tryAcquireNanos(Integer.parseInt(Thread.currentThread().getName()), TimeUnit.MILLISECONDS.toNanos(1000));
}while(!result);
for (int i = 0; i < color.length(); i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.exit(-1);
}
System.out.print("" + color.charAt(i) + " ");
}
} catch (NumberFormatException e1) {
e1.printStackTrace();
} catch (InterruptedException e1) {
e1.printStackTrace();
}finally{
cb.release(Integer.parseInt(Thread.currentThread().getName()));
}
}
}
}
new Thread(new ColouredRunnable("RED"), "0").start();
new Thread(new ColouredRunnable("BLUE"), "1").start();
new Thread(new ColouredRunnable("GREEN"), "2").start();
new Thread(new ColouredRunnable("BLACK"), "3").start();
new Thread(new ColouredRunnable("MAGENTA"), "4").start();
new Thread(new ColouredRunnable("WHITE"), "5").start();
}
}
public class TestSynchronizer extends AbstractQueuedSynchronizer{
/**
*
*/
private static final long serialVersionUID = 1L;
int count;
public TestSynchronizer(int count) {
this.count = count;
setState(0);
}
#Override
protected boolean tryAcquire(int arg) {
if(arg == getState()){
System.out.println("Acquires" + Thread.currentThread().getName());
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
#Override
protected boolean tryRelease(int arg) {
int state = getState();
setState(++state % count);
setExclusiveOwnerThread(null);
return true;
}
}
How to use it?
Synchronizer takes one argument count that is for upto how many threads have to synchronize.
The names of the threads MUST be the order they need to take. Now you can add as many threads to it as you need.
I have designed a custom Synchronizer and used that to define a new policy for allowing locking and unlocking of threads.
Phasers are pretty cool for this too if you want to play with them. All this one requires is that you populate the words list with whatever words you want - it makes a thread for each word and they all play nicely.
public class PhaserTest
{
private final Phaser phaser = new Phaser(1) {
protected boolean onAdvance(int phase, int parties)
{
//Phaser version of your CyclicBarrier Runnable
if(parties == 1)
System.out.println("\n-------------");
return false;
}
};
public void runTest()
{
List<String> words = Arrays.asList("RED", "BLUE", "GREEN");
for(int i = 0; i < words.size();i++)
new Thread(new ColouredRunnable(words.get(i),i + 1)).start();
while(phaser.arriveAndAwaitAdvance() != (words.size() + 1)){}
System.out.println("Done.");
}
public class ColouredRunnable implements Runnable {
private final int order;
private final String color;
public ColouredRunnable(String s, int order) {
this.color = s;
this.order = order;
phaser.register();
}
#Override
public void run() {
while(phaser.arriveAndAwaitAdvance() != order){}
for (int i = 0; i < color.length(); i++) {
sleep();
System.out.print("" + color.charAt(i) + " ");
}
phaser.arriveAndDeregister();
}
private void sleep() {
try {
Thread.sleep(ThreadLocalRandom.current().nextLong(200, 600));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
This solution uses 3 cyclic barriers. Code initially creates a managed deadlock between threads using cyclic barriers. Deadlock is broken by triggering cb[cb.length-1].await(); in main thread
public static void main(String[] args) {
String colors[] = { "RED", "BLUE", "GREEN" };
final CyclicBarrier[] cb = createCB(colors);
for (int i = 0; i < colors.length; i++) {
final int j = i;
new Thread(colors[i]) {
public void run() {
while (true) {
try {
cb[(j == 0 ? cb.length : j) - 1].await();// Wait for
// previous
// barrier
String name = getName();
for (int i = 0; i < name.length(); i++) {
CyclicBari.sleep();
System.out.print(" " + name.charAt(i) + " ");
}
cb[j].await();// Notify next
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}.start();
}
System.out.println("start");
try {
cb[cb.length-1].await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
private static void sleep() {
try {
Thread.sleep(ThreadLocalRandom.current().nextLong(200, 600));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static CyclicBarrier[] createCB(String[] colors) {
final CyclicBarrier cb[] = new CyclicBarrier[colors.length];
for (int i = 0; i < cb.length; i++) {
final int j = i;
cb[i] = new CyclicBarrier(2, new Runnable() {
#Override
public void run() {
if (j == cb.length - 1) {
System.out.println("\n-------------");
} else {
System.out.print(".");
}
}
});
}
return cb;
}
Output
-------------
R E D . B L U E . G R E E N
-------------
R E D . B L U E . G R E E N
-------------
R E D . B L U E . G R E E N
-------------

Thread-managed objects not entering a stack on another thread

Follow-up on a previous question I posted about a combat simulator.
The problem here: 'Creature' objects do not enter the stack on the 'Combat' class.
The whole thing is several classes larger but I've managed to narrow the problem to the following code.
public class Combat implements Runnable {
int Turn = 0;
HashMap<Integer, Faction> Factions = new HashMap<Integer, Faction>();
Stack<Creature> stack;
public int getFactionsStanding() {
int Result = 0;
Iterator<Faction> F = Factions.values().iterator();
while(F.hasNext()) {
if (F.next().getMemberCount() > 0)
Result = Result + 1;
}
return Result;
}
public HashMap<Integer, Creature> getEnemies(int factionID) throws NoFactionsException {
HashMap<Integer, Creature> targetPool = new HashMap<Integer, Creature>();
Iterator<Faction> F = Factions.values().iterator();
if (!(F.hasNext()))
throw new NoFactionsException();
Faction tempFaction;
while (F.hasNext()){
tempFaction = F.next();
if (tempFaction.getfactionID() != factionID)
targetPool.putAll(tempFaction.getMembers());
}
return targetPool;
}
private int getMaxInit(){
int Max = 0, temp = 0;
Iterator<Faction> I = Factions.values().iterator();
while(I.hasNext()){
temp = I.next().getMaxInit();
if (temp > Max)
Max = temp;
}
return Max;
}
public int getTurn() {
return Turn;
}
public void setTurn(int turn) {
Turn = turn;
}
// TODO I can't get creatures to enter the stack! :#
synchronized public void push(Creature C){
stack.push(C);
System.out.println("Creature " + C.getName() + " is now on the stack");
if (C.getInit() == this.getMaxInit())
this.emptyStack();
notify();
}
// TODO The stack must be processed now: everyone does what they intended to do
public void emptyStack(){
Creature C;
while (!(stack.isEmpty())){
C = stack.pop();
C.takeAction();
}
Turn = 0;
}
synchronized public void increaseTurn(){
this.Turn = Turn + 1;
System.out.println("Current initiative score is " + this.getTurn());
notifyAll();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
}
public void run(){
while(this.getFactionsStanding() > 1){
increaseTurn();
}
}
}
public class Creature extends Observable implements Runnable {
synchronized public void declareAction(){
try{
if (Combat.getTurn() != this.getInit())
wait();
Combat.push(this);
}
catch (InterruptedException e){
return;
}
}
public void takeAction(){
Attack(this.Target, this.leftHandWeapon);
if (this.Target.getCurrentHP() < 0)
this.Target = null;
}
public void setTarget() {
Integer targetID = -1;
HashMap<Integer, Creature> targetPool;
Object[] targetKeys;
try{
targetPool = Combat.getEnemies(FID);
if (targetPool.isEmpty())
throw new EmptyTargetPoolException();
targetKeys = targetPool.keySet().toArray();
if (targetKeys.length == 0)
throw new EmptyTargetKeysArrayException();
if (this.Target == null) {
do{
targetID = (Integer) this.getRandom(targetKeys); //(Integer)targetKeys[(Integer) this.getRandom(targetKeys)];
} while (!(targetPool.keySet().contains((Integer)targetID)));
this.Target = targetPool.get(targetID);
}
}
catch (EmptyTargetPoolException e) {
System.out.println(e.getMessage());
}
catch (EmptyTargetKeysArrayException e) {
System.out.println(e.getMessage());
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void run() {
// This will go on and on as long as this creature is alive
while (this.currentHP > 0) {
try {
this.setInit();
this.setTarget();
this.declareAction();
}
catch (Exception e){
System.out.println(e.getMessage());
}
}
System.out.println(this.Name + " was killed!");
}
}
Does the creatures name get printed out? If so there may be a problem with:
if (C.getInit() == this.getMaxInit())
this.emptyStack();
I'm not sure what the method getInit() does but if getMaxInit() also returns the same value then it could just empty the stack each time push() is called. Its the only problem I can see right now that could happen.

Categories