Follow the path of eventList please. While it stores the proper objects as it's supposed to initially, it empties itself as soon as it enters MouseClicked(). There is a driver used to run initialize() in another class. I just can't seem to get eventList to hold its information.
public class Adventure_Chapter1 implements MouseListener
{
boolean success = true;
ArrayList<StoryEvent> eventList = new ArrayList<StoryEvent>();
public void initiliaze() throws FontFormatException, IOException
{
load(); // loads StoryEvents
play(0);
System.out.println("Init() eventList size: " + eventList.size());
}
private void load()
{
int x = 0;
switch(x)
{
case 0:
StoryEvent txt0 = new StoryEvent(parameters);
eventList.add(txt0);
case 1:
StoryEvent assassinStart = new StoryEvent(parameters);
eventList.add(assassinStart);
}
}
public void updatePlayer()
{
System.out.println("Player Updated ");
}
public void play(int c) // to be implemented
{
storyLineDisplay.setText("testing");
System.out.println("Play() eventList size:" + eventList.size());
//int c would typically change my buttons' options next to them. but for now it
is irrelevant.
}
public void mouseClicked(MouseEvent e)
{
if (e.getSource().equals(buttonOne));
{
if (success == true)
{
updatePlayer();
System.out.println("MouseClicked eventList size: " + eventList.size());
play(1);
}
else
{
updatePlayer();
currentCharacter.add(eventList.get(choice));
choice = currentCharacter.get(currentCharacter.size() -1).getFail1();
play(1);
}
}
}
Output is here:
Play() eventList size:2
Init() eventList size: 2
Player Updated
MouseClicked eventList size: 0
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at Adventure_Chapter1.mouseClicked(Adventure_Chapter1.java:277)
insert further lines of errors here.
You should break your switch statements.
if (success == true)
can be replaced by
if (success)
if (e.getSource().equals(buttonOne));
must be replaced by
if (e.getSource().equals(buttonOne))
put all of the involved code if you want help with debugging, we are not mind readers and guessers. Obviously there are missing code.
Edited
Can we see the code for StoryEvent. Are you touching the evenList list there
? Otherwise I don't understand how you get two elements in your
evenList, to begin with.
public void mouseClicked(MouseEvent e)
{
if (e.getSource().equals(buttonOne));
{
if (success == true)
{
updatePlayer();
System.out.println("MouseClicked eventList size: " + eventList.size());
play(choice);
}
else
{
updatePlayer();
currentCharacter.add(eventList.get(choice));
choice = currentCharacter.get(currentCharacter.size() -1).getFail1();
}
}
}
but what is "choice" ?
Related
I am trying to operate on the same source with two threads. I designed a typical producer and consumer problem for it. While setting the value in the resource class with the producer, I want to get setted values with the consumer one by one. The output I want should be like this:
Producer -> Setting data = 0
Consumer -> Getting data = 0
Producer -> Setting data = 1
Consumer -> Getting data = 1
Producer -> Setting data = 2
Consumer -> Getting data = 2
Producer -> Setting data = 3
Consumer -> Getting data = 3
Producer -> Setting data = 4
Consumer -> Getting data = 4
Here is my Resource class:
public class Resource{
private int value;
private boolean current = false;
public synchronized void setValue(int val) {
while(current == true) {
try {
wait();
}catch(Exception ex) {}}
value = val;
current = true;
notifyAll();
}
public synchronized int getValue() {
while(current == false) {
try {
wait();
}catch(Exception ex) {}}
current = false;
notifyAll();
return value;
}
}
And main method and Producer,Consumer class is here:
class Producer extends Thread{
private Resource rs;
public Producer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
rs.setValue(i);
System.out.println("Producer -> Setting data = " + i);
try {
sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Resource rs;
public Consumer(Resource rs1) {
rs = rs1;
}
public void run() {
int value = 0;
for(int i = 0 ; i < 5; i++) {
value = rs.getValue();
System.out.println("Consumer -> Getting data= " + i);
try {
sleep(100);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
public class Dependent {
public static void main(String[] args) throws IOException {
Resource res = new Resource();
Producer p1 = new Producer(res);
Consumer c1 = new Consumer(res);
p1.start();
c1.start();
}
}
Although I use synchronized, wait and notifyAll keywords in the methods in the resource class, the threads continue to work without waiting for each other. Where am I making a mistake? I've seen a code sample similar to this code sample in a java book, there doesn't seem to be a problem.
When I write without adding the current boolean variable, the code doesn't even work. That's why I had to add it by looking from the book. Don't the threads need to work synchronously without checking the Current value?
They do wait for each other, but the thread sync operations are much, much faster than Thread.sleep(100) so you can't tell. Your test code prints 'i' and not 'value', which is suspect. Get rid of Thread.sleep(100) in one of these threads (for example, in the consumer) and you'll find that the consumer nevertheless still requires about half a second to complete - as it will be waiting about 100 msec every time it invokes .getValue() on the resource, because that call will block (stuck in that wait() loop) until the producer calls .setValue which it only does about once every 100 msec.
Your Resource object 'works', for some value of 'works', but is very poorly designed, re-creating already existing and better implemented classes from the core library such as a java.util.concurrent.Latch, and which ignore interrupts and will blindly just keep waiting.
Their APIs are also a tad oddly named, in that a get call has considerably side effects. get is more of a get and clear operation: After a get operation, another get operation will freeze the thread forever, or at least, until some thread sets a value.
How do you think?
import java.io.IOException;
class Resource {
private volatile Integer value;
public synchronized void setValue(int val) {
while(value != null && !value.equals(val)) {
try {
wait();
}catch(Exception ex) {}}
value = val;
notifyAll();
}
public synchronized int getValue() {
while(value == null) {
try {
wait();
}catch(Exception ex) {}}
int answer = value;
value = null;
notifyAll();
return answer;
}
}
class Producer extends Thread{
private Resource rs;
public Producer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5 ; i++) {
rs.setValue(i);
System.out.println("Producer -> Setting data = " + i);
try {
sleep(100);
}catch(Exception ex){
ex.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Resource rs;
public Consumer(Resource rs1) {
rs = rs1;
}
public void run() {
for(int i = 0 ; i < 5; i++) {
int value = rs.getValue();
System.out.println("Consumer -> Getting data= " + value);
try {
sleep(100);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
}
public class Dependent {
public static void main(String[] args) throws IOException {
Resource res = new Resource();
Producer p1 = new Producer(res);
Consumer c1 = new Consumer(res);
p1.start();
c1.start();
}
}
or
class Resource {
private static final int WAIT_VALUE = -1;
private volatile int value = WAIT_VALUE;
public synchronized void setValue(int val) {
while(value > WAIT_VALUE && value != val) {
try {
wait();
}catch(Exception ex) {}}
value = val;
notifyAll();
}
public synchronized int getValue() {
while(value == WAIT_VALUE) {
try {
wait();
}catch(Exception ex) {}}
int answer = value;
value = WAIT_VALUE;
notifyAll();
return answer;
}
}
I wanted to say for a school project in Greenfoot, that if a rover encounters a system error, it should output this and then wait a short time and then terminate the current method. However, the pause is marked with the following error code: unreported exception java. lang. InterupptedException; must be cought or declared to be thrown, as I am very new to Java I have no idea what to change. Besides, he should then end the method, but with the current command the whole scenario is ended.
"
public Rover (String pname, char pfrequenz, int penergie)
{
energie = penergie;
name = pname;
temp = 15 ;
distance = 0;
systemcheck = true;
frequenz = pfrequenz ;
}
public void check()
{
if (markeVorhanden())
{
energie = energie + 100;
}
if (energie == 0){
systemcheck = false;
}
if (systemcheck = false){
nachricht("System Failure");
java.util.concurrent.TimeUnit.SECONDS.sleep(2);
System.exit(0);
}
if (distance > 100){
nachricht("Congrats you have passed 100");
}
anzeige.anzeigen("Akku: "+energie+ " %");
}
Try this
import java.io.*;
public class Yourclass{
public void Rover (String pname, char pfrequenz, int penergie)
{
Integer energie = penergie;
String name = pname;
Integer temp = 15 ;
Integer distance = 0;
boolean systemcheck = true;
char frequenz = pfrequenz ;
}
public void check() throws IOException
{
if (markeVorhanden())
{
energie = energie + 100;
}
if (energie == 0){
systemcheck = false;
}
if (systemcheck = false){
nachricht("System Failure");
throw new IOException("sorry device error");
}
if (distance > 100){
nachricht("Congrats you have passed 100");
}
anzeige.anzeigen("Akku: "+energie+ " %");
}
public static void main(String []args) throws InterruptedException
{
Yourclass demo= new Yourclass();
System.out.println("Hello World");
try{
demo.check();
}
catch(Exception e)
{
Thread.sleep(2000);
System.out.println("function stopped");
}
}
}
You will have to read up on exception handling in Java. The sleep method may get interrupted and may thus raise an InterruptedException. You can either forward this exception or ignore it.
To forward the exception, declare the function a
public void check() throws InterruptedException
but then callers of this function will have to deal with that potential exception. Since interrupted does not look a severe problem here (the sleep is just a bit shorter than the two seconds), it may be fine to ignore the exception:
try { java.util.concurrent.TimeUnit.SECONDS.sleep(2); }
catch (InterruptedException ignored) {}
In order to just return from the current method use return instead of System.exit()
I'm having this errors:
1) Cannot cast from HashBasedTable to Table .
This is the code in error: In the line:
this.restores = **(Table<UUID, PotionEffectType, PotionEffect>)HashBasedTable.create()**;
2) The method put(UUID, PotionEffectType, PotionEffect) in the type Table is not applicable for the arguments (Object, Object, Object)
This is the code in error: In the line:
this.restores.**put**((Object)player.getUniqueId(), (Object)active.getType(), (Object)active);
public class MageRestorer implements Listener
{
private final Table<UUID, PotionEffectType, PotionEffect> restores;
public MageRestorer(final HCF plugin) {
this.restores = (Table<UUID, PotionEffectType, PotionEffect>)HashBasedTable.create();
plugin.getServer().getPluginManager().registerEvents((Listener)this, (Plugin)plugin);
}
#EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPvpClassUnequip(final PvpClassUnequipEvent event) {
this.restores.rowKeySet().remove(event.getPlayer().getUniqueId());
}
public void setRestoreEffect(final Player player, final PotionEffect effect) {
boolean shouldCancel = true;
final Collection<PotionEffect> activeList = (Collection<PotionEffect>)player.getActivePotionEffects();
for (final PotionEffect active : activeList) {
if (active.getType().equals((Object)effect.getType())) {
if (effect.getAmplifier() < active.getAmplifier()) {
return;
}
if (effect.getAmplifier() == active.getAmplifier() && effect.getDuration() < active.getDuration()) {
return;
}
this.restores.put((Object)player.getUniqueId(), (Object)active.getType(), (Object)active);
shouldCancel = false;
}
}
player.addPotionEffect(effect, true);
if (shouldCancel && effect.getDuration() > 100 && effect.getDuration() < MageClass.DEFAULT_MAX_DURATION) {
this.restores.remove((Object)player.getUniqueId(), (Object)effect.getType());
}
}
#EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void onPotionEffectExpire(final PotionEffectExpiresEvent event) {
final LivingEntity livingEntity = event.getEntity();
if (livingEntity instanceof Player) {
final Player player = (Player)livingEntity;
final PotionEffect previous = (PotionEffect)this.restores.remove((Object)player.getUniqueId(), (Object)event.getEffect().getType());
if (previous != null) {
new BukkitRunnable() {
public void run() {
player.addPotionEffect(previous, true);
}
}.runTask((Plugin)HCF.getPlugin());
}
}
}
}
I dont know fix this. This is a clase of bukkit
For the first error, can we see the stack trace? Also, why do you need to cast it? You can store it as a Table; a cast is unnecessary.
For the second error, remove the casts to Object. Simply leave them as their actual types. this.restores.put(player.getUniqueId(), active.getType(), active);
This should help you get through the issue.
I have a program that simulates Gates to a ship. They run in threads. The idea is to let them run and pause during a random moment in the run method to simulate persons passing. This is done by all threads, meanwhile the main thread is waiting for notification and checking if the ship is getting full when notified by the threads that they added a person passing through the gate the main thread checks again if the ship is full. The program has three classes:
A counter:
public class Counter {
private int currentValue[];
private int maxValue;
public Counter(int[] nrOfPeople, int max) {
currentValue = nrOfPeople;
currentValue[0] = 0;
maxValue = max;
}
public synchronized void addPersons(int nr_p) {
currentValue[0] += nr_p;
}
public synchronized int getValue() {
return currentValue[0];
}
public synchronized boolean isFull() {
if(currentValue[0] < maxValue)
return false;
return true;
}
}
A Gate Class:
public abstract class Gate implements Runnable {
int nrOfPassengers;
int gatenr;
int gatesize;
Counter c;
private Thread t;
private Random r;
private boolean blocked; /* suspends people from passing */
public Gate(Counter c, int nr) {
this.c = c;
gatenr = nr;
this.open();
r = new Random();
t = new Thread(this);
t.start();
}
public void setGatesize(int size) {
gatesize = size;
}
public void close() {
blocked = true;
}
public void open() {
blocked = false;
}
public int getNoOfPassangers() {
return nrOfPassengers;
}
public int getId() {
return gatenr;
}
#Override
public void run() {
while(!blocked) {
int waitTime = (r.nextInt(5) + 1) * 1000; /* between 1-5 seconds */
System.out.println("Person-Gate " + gatenr + ": adding one to " + c.getValue());
try {
/* bigger throughput => amount can vary */
if(gatesize > 1) {
int persons = r.nextInt(gatesize)+1;
c.addPersons(persons);
nrOfPassengers += persons;
} else {
c.addPersons(1);
nrOfPassengers++;
}
Thread.sleep(waitTime);
} catch (InterruptedException e) {
System.out.println("Person-Gate " + gatenr + ": was interrupted adding person");
e.printStackTrace();
}
System.out.println("Person-Gate " + gatenr + ": added one to " + c.getValue());
t.notify();
}
}
public void join() {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
And a Simulator that runs the main method:
/*
* This class simulates cars and persons- entering a ferry.
*/
public class Simulator {
public static final int MAX = 30;
public static void main(String[] args) {
int nrOfPeople[] = new int[1]; /* array of size one for keeping count */
ArrayList<Gate> gates = new ArrayList<Gate>();
Counter counter = new Counter(nrOfPeople, MAX);
Thread mainThread = Thread.currentThread();
/* adding 3 person-gates */
for(int i=1; i<4; i++) {
gates.add(new PersonGate(counter, i));
}
/* let all gates work as long as passengers is under MAX */
while(!counter.isFull()) {
try {
mainThread.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Announcement: Ship is full!");
/* wait for child threads to finish */
for(Gate g: gates) {
g.close();
try {
g.join();
} catch (Exception e) { /* InterruptedException */
e.printStackTrace();
}
System.out.println(g.getNoOfPassangers() + " passed through gate nr " + g.getId());
System.out.println(counter.getValue() + " has passed in total");
}
}
}
Im getting a error
Person-Gate 1: adding one to 0
Person-Gate 2: adding one to 1
Person-Gate 3: adding one to 2
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at Simulator.main(Simulator.java:24)
Person-Gate 3: added one to 3Exception in thread "Thread-3"
Does anyone now whats going on?
You can only call wait and notify/notifyAll from within synchronized blocks.
t.notify();
You are notifying wrong monitor. This exception occurs, when you do not wrap monitor object with synchronize section. However, objects which you are using for notify and for wait methods are different. Create new Object() monitor and pass it to the constructor of Gate.
Also you can take a look at CountDownLatch, it does exactly what you are trying to achieve.
You must own the monitor of the object on which you call wait or notify. Meaning, you must be in a synchonize-Block, like
synchronized( objectUsedAsSynchronizer) {
while ( mustStillWait) {
objectUsedAsSynchronizer.wait();
}
}
This has been the subject of many other questions.
I'm having a bit of a problem with writing a multithreaded algorithm in Java. Here's what I've got:
public class NNDFS implements NDFS {
//Array of all worker threads
private Thread[] threadArray;
//Concurrent HashMap containing a mapping of graph-states and
//algorithm specific state objects (NDFSState)
private ConcurrentHashMap<State, NDFSState> stateStore;
//Whether the algorithm is done and whether a cycle is found
private volatile boolean done;
private volatile boolean cycleFound;
/**
Constructor that creates the threads, each with their own graph
#param file The file from which we can create the graph
#param stateStore Mapping between graph-states and state belonging to our algorithm
#param nrWorkers Number of working threads we need
*/
public NNDFS(File file, Map<State, NDFSState> stateStore, int nrWorkers) throws FileNotFoundException {
int i;
this.stateStore = new ConcurrentHashMap<State, NDFSState>(stateStore);
threadArray = new Thread[nrWorkers];
for(i=0;i<nrWorkers;i++){
Graph graph = GraphFactory.createGraph(file);
threadArray[i] = new Thread(new NDFSRunnable(graph, i));
}
}
/**
Class which implements a single thread running the NDFS algorithm
*/
class NDFSRunnable implements Runnable{
private Graph graph;
//Neccesary as Java apparently doesn't allow us to get this ID
private long threadId;
NDFSRunnable(Graph graph, long threadId){
this.graph = graph;
this.threadId = threadId;
}
public void run(){
try {
System.out.printf("Thread id = %d\n", threadId);
//Start by executing the blue DFS for the first graph
mcdfsBlue(graph.getInitialState(), threadId);
} catch (CycleFound e) {
//We must catch all exceptions that are thrown from within our thread
//If exceptions "exit" the thread, the thread will silently fail
//and we dont want that. We use 2 booleans instead, to indicate the status of the algorithm
cycleFound = true;
}
//Either the algorithm was aborted because of a CycleFound exception
//or we completed our Blue DFS without finding a cycle. We are done!
done = true;
}
public void mcdfsBlue(State s, long id) throws CycleFound {
if(done == true){
return;
}
//System.out.printf("Thread %d begint nu aan een dfsblue\n", id);
int i;
int counter = 0;
NDFSState state = stateStore.get(s);
if(state == null){
state = new NDFSState();
stateStore.put(s,state);
}
state.setColor(id, Color.CYAN);
List<State> children = graph.post(s);
i = state.incNextBlue();
while(counter != children.size()){
NDFSState child = stateStore.get(children.get(i%children.size()));
if(child == null){
child = new NDFSState();
stateStore.put(children.get(i % children.size()),child);
}
if(child.getLocalColor(id) == Color.WHITE && !child.isRed()){
mcdfsBlue(children.get(i % children.size()), id);
}
i++;
counter++;
}
if(s.isAccepting()){
state.incRedDFSCount();
mcdfsRed(s, id);
}
state.setColor(id, Color.BLUE);
}
public void mcdfsRed(State s, long id) throws CycleFound {
if(done == true){
return;
}
int i;
int counter = 0;
NDFSState state = stateStore.get(s);
state.setPink(id, true);
List<State> children = graph.post(s);
i = state.incNextRed();
while(counter != children.size()){
NDFSState child = stateStore.get(children.get(i%children.size()));
if(child == null){
child = new NDFSState();
stateStore.put(children.get(i%children.size()),child);
}
if(child.getLocalColor(id) == Color.CYAN){
throw new CycleFound();
}
if(!child.isPink(id) && !child.isRed()){
mcdfsRed(children.get(i%children.size()), id);
}
i++;
counter++;
}
if(s.isAccepting()){
state.decRedDFSCountAndWait();
}
state.setRed();
state.setPink(id, false);
}
}
public void init() {}
public void ndfs() throws Result {
int i;
done = false;
cycleFound = false;
for(i=0;i<threadArray.length;i++){
System.out.printf("Launch thread %d\n",i);
threadArray[i].run();
}
try {
for(i=0;i<threadArray.length;i++){
threadArray[i].join();
}
} catch (InterruptedException e) {
}
//We want to show the result by throwing an exception (weird, but yeah :-/)
if (cycleFound) {
throw new CycleFound();
} else {
throw new NoCycleFound();
}
}
}
However, when I run this, it seems like the first thread is called, completes, and then the next is called etc. What I want obviously, is that all threads are started simultaneously! Otherwise the algorithm has very little use...
Thanks for your time/help!
Regards,
Linus
Use threadArray[i].start(); to launch your thread.
If you use threadArray[i].run();, all it does is call the method normally, in the same thread as the caller.