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.
Related
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
}
I want to use two threads to print Floyd triangle(say one thread prints the number and the other prints the number in the line) as below.
and so forth until the max number which is 15 in this case.
I tried following but it keeps on printing numbers one on each line
public class MyThread extends Thread{
static volatile int lineNumber = 1;
public static void main(String... args) {
PrintFloyd print = new PrintFloyd();
Thread t1 = new Thread(new TaskHandler(print, 10), "T1");
Thread t2 = new Thread(new TaskHandler(print, 10), "T2");
t1.start();
t2.start();
}
}
class TaskHandler implements Runnable {
static volatile int i = 1;
static volatile int lineCount = 1;
static volatile int lineNumber = 1;
private int max;
private PrintFloyd print;
TaskHandler(PrintFloyd print2, int max) {
this.print = print2;
this.max = max;
}
#Override
public void run() {
System.out.println(">>>>" + Thread.currentThread().getName());
while(i < max){
if (Thread.currentThread().getName().equals("T1")){
print.printNumber(i);
} else {
print.breakLine();
}
}
}
}
class PrintFloyd {
boolean isBreakPoint = false;
public void printNumber(int i) {
synchronized(this){
while (isBreakPoint == false) {
try {
wait();
} catch (InterruptedException ex) {
}
System.out.print(i++ + " ");
isBreakPoint = false;
notifyAll();
}
}
}
public void breakLine(){
synchronized(this){
while (isBreakPoint == true) {
try {
wait();
} catch (InterruptedException ex) {
}
}
System.out.println();
isBreakPoint = true;
notifyAll();
}
}
}
The following code would help:
public class PrintPatternWith2Threads {
final static int MAX = 15;
final static String itemWriterName = "itemWriter";
final static String newLineWriterName = "newLineWriter";
public static void main(String[] args) {
Printer print = new Printer(MAX);
Thread itemWriter = new Thread(new ItemWriter(print), itemWriterName);
itemWriter.start();
Thread newLineWriter = new Thread(new NewLineWriter(print), newLineWriterName);
newLineWriter.start();
}
}
class ItemWriter implements Runnable {
private Printer print;
ItemWriter(Printer print) {
this.print = print;
}
public void run() {
while (print.current <= print.MAX) {
print.printNumber();
}
}
}
class NewLineWriter implements Runnable {
private Printer print;
NewLineWriter(Printer print) {
this.print = print;
}
public void run() {
while (print.current <= print.MAX) {
print.printNewLine();
}
}
}
class Printer {
public final int MAX;
public int current = 1;
public int itemsInALine = 1;
Printer(int max) {
this.MAX = max;
}
public void printNumber() {
synchronized(this) {
for(int i = current; i < current + itemsInALine && i <= MAX; i++) {
System.out.print(i + " ");
}
this.current = current + itemsInALine;
itemsInALine++;
notifyAll();
try {
if(this.current < MAX) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void printNewLine() {
synchronized(this) {
System.out.println();
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
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();
}
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);
}
}
}
}
I have this producer Consumer sample Program shown below
How can i put a Condition inside my Consumer Thread class so that if i didn't recivied the data from producer for 1 minute , i need to log that ??
This is my Producer Consumer Program
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() {
while (available == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll();
}
}
class Producer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
while(true)
{
for (int i = 0; i < 100000; i++) {
cubbyhole.put(i);
System.out.println("Producer #" + this.number + " put: " + i);
try {
sleep((int) (Math.random() * 2000));
} catch (Exception e) {
}
}
}
}
}
class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
while(true)
{
int value = 0;
for (int i = 0; i < 100000; i++) {
value = cubbyhole.get();
System.out.println("Consumer #" + this.number + " got: " + value);
}
}
}
}
Could anybody please help
You could use Object#wait(long timeout) and log from inside the get() method:
try {
wait(60 * 1000);
if (available == false) {
//log
}
} catch (InterruptedException e) {
}
Use System.currentTimeMilis() in your Consumer run method:
long before;
for (int i = 0; i < 100000; i++) {
before = System.currentTimeMilis();
value = cubbyhole.get();
if (System.currentTimeMilis() - before > 1000 * 60) {
System.out.println("Consumer waited for more than one minute");
}
System.out.println("Consumer #" + this.number + " got: " + value);
}