Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have the following code, but I want it to run once every second, so if questNumber changes, then currentQuestStats will also change.
Editor's note: pastebin link with code that used to be here no longer works.
use ScheduledExecutorService which added in JAVA 5, you must import following classes.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
you can use it like below:
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// TODO add your code here:
}
}, 0, 1, TimeUnit.SECONDS);
Answer
make a method called checkQuestNumber() in QuestsManagement class.
also create a constructor for QuestsManagement
initialize currentQuestStats with this value (§e§lCurrent quest: Kill 1 zombie).
make currentQuestStats and questNumber private and encapsulate them.
here is your QuestsManagement after those changes
public class QuestsManagement {
private String currentQuestStats = "§e§lCurrent quest: Kill 1 zombie";
private int questNumber = 1;
public String getCurrentQuestStats() {
return currentQuestStats;
}
public int getQuestNumber() {
return questNumber;
}
QuestsManagement() {
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
checkQuestNumber();
}
}, 0, 1, TimeUnit.SECONDS);
}
void checkQuestNumber() {
if (questNumber == 1) {
currentQuestStats = "§e§lCurrent quest: Kill 1 zombie";
// change manual!
questNumber = 2;
} else if (questNumber == 2) {
currentQuestStats = "§e§lCurrent quest: Walk 100 blocks";
// change manual!
questNumber = 1;
}
}
}
To Test Code!
in your custom command file
create an instance of QuestsManagement and use getCurrentQuestStats() method
QuestsManagement m = new QuestsManagement();
player.addChatMessage("Test" + QuestsManagement.getCurrentQuestStats());
Do it using multithreading. Here's the code:
public class QuestsManagement implements Runnable{
public String currentQuestStats = "";
public int questNumber = 1;
Thread t;
#Override
public void run() {
try {
if(questNumber == 1) {
currentQuestStats = "§e§lCurrent quest: Kill 1 zombie";
if(questNumber == 2) {
currentQuestStats = "§e§lCurrent quest: Walk 100 blocks";
}
}
Thread.sleep(1000);
}
catch(Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
Thread t = new Thread(new QuestsManagement());
t.start();
//do something else here... whatever you want to do
}
}
First of all, you need to add all of the code you want to run to a method. I will assume you will call it update().
What you then want to do is add something like the following to your main program loop:
long nextTick = currentTimeMillis() + 1000 ;//Set time of first game tick
QuestsManagement quest = new QuestsManagement();
//Main Loop
while (true) {
/*
Do some other stuff
*/
if (System. currentTimeMillis() >= nextTick) {//Check to see if it is time or past time to update
nextTick += 1000//Set next tick to one second in the future
quest.update();
}
}
Please note that you are missing the update() method, the constructor, and any getters and setters. I would also refrain from making your variables public.
Well, there are multiple answers possible to this question. Java provides various ways to perform time operations. One approach is to use Timer class.
public class QuestsManagement {
public String currentQuestStats = "";
public int questNumber = 1;
static Timer t;
TimerTask task;
public static void main(String[] args) {
t = new Timer();
task = new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
if(questNumber == 1) {
currentQuestStats = "§e§lCurrent quest: Kill 1 zombie";
if(questNumber == 2) {
currentQuestStats = "§e§lCurrent quest: Walk 100 blocks";
}
} ;
t.scheduleAtFixedRate(task , 1000, 1000 );
}}
import following
import java.util.Timer;
import java.util.TimerTask;
Related
I'm going to try to explain this the best I can, and hopefully you can understand my problem.
I'm designing a processor simulation program in Java, and right now I'm currently coding the "clock unit" which is going to control the program's execution. Basically, I have a class ClockUnit that changes state between 0 and 1 periodically. I need a second class Processor to be able to know when the clockunit class changes state, and then executes an instruction. So...
ClockUnit state = 0.
Processor does nothing.
ClockUnit change state = 1.
Processor executes instruction
At the moment I am running the ClockUnit class within a thread, I now need a way to run the Processor class and allow it to constantly check the state of the clock and when it changes to a 1 to execute an instruction. I'm not sure how to do this.
Do I need to create a second thread and run the Processor class from the second thread?
I hope it's clear what I need to happen. In my head its quite a simple task, I just need one thread to constantly check the state of another, but I'm not sure how to go about it.
I have posted my code below. There isn't really much complexity to it.
Main class
public class Main {
private static ALU alu;
private static ClockThread clockThread;
public static void main(String[] args)
{
//two threads, both running at the same time, one thread has clock ticking, other thread gets state of ticking clock and executes on rising edge
alu = new ALU();
clockThread = new ClockThread("clockThread", 1);
clockThread.start();
while(clockThread.getClock().getState() == 1)
{
System.out.println("ON");
}
}
}
ClockThread class
import java.util.Timer;
public class ClockThread extends Thread {
private String threadName;
private double instructionsPerSecond;
private Timer timer;
private Clock clockUnit;
public ClockThread(String name, double insPerSec)
{
threadName = name;
System.out.println("Clock thread initialised");
instructionsPerSecond = insPerSec;
}
public void run()
{
clockUnit = new Clock(instructionsPerSecond);
timer = new Timer();
timer.scheduleAtFixedRate(clockUnit, 0, (long) (clockUnit.timePeriod() * 1000));
}
public Clock getClock()
{
return clockUnit;
}
}
Clock class
import java.util.TimerTask;
public class Clock extends TimerTask{
private int state = 0; //the state of the simulation, instrutions will execute on the rising edge;
private double executionSpeed; //in Hz (instructions per second)
private String threadName = "Clock";
public Clock(double instructionsPerSecond)
{
executionSpeed = instructionsPerSecond;
System.out.println("[Clock] Execution speed set to " + executionSpeed + "Hz. (" + timePeriod() + "s per instruction.)");
}
public void run()
{
toggleState();
System.out.println("System State: " + state);
}
public void toggleState()
{
if(state == 1)
{
state = 0;
}
else if(state == 0)
{
state = 1;
}
}
public double timePeriod() //takes the number of instructions per second (hz) and returns the period T (T = 1/f);
{
double period = 1/executionSpeed;
return period;
}
public double getExecutionSpeed()
{
return executionSpeed;
}
public int getState()
{
return state;
}
}
Since you already have a reliable clock source (the producer), you can use a BlockingQueue to send 'EdgeChange' alerts to the ALU? (the unit responsible for executing instructions). The clock source will 'offer' the edge change event, and the ALU? will receive it (and subsequently do work). Here is the slight changes to your code to share events across objects in different threads:
Main:
public static void main(String[] args) {
BlockingQueue<Integer> edgeAlerts = new ArrayBlockingQueue<Integer>(2);
clockThread = new ClockThread("clockThread", 1, edgeAlerts);
clockThread.start();
boolean isInterrupted = false;
while(!isInterrupted) {
try {
Integer edgeValue = edgeAlerts.take();
if (edgeValue == 1) {
System.out.println("Executing instruction");
// Perform the instruction
}
} catch (InterruptedException e) {
isInterrupted = true;
}
}
}
You have to pass the BlockingQueue to your ClockThread ...
private final BlockingQueue<Integer> edgeAlerts;
public ClockThread(String name, double insPerSec, BlockingQueue<Integer> edgeAlerts)
{
threadName = name;
this.edgeAlerts = edgeAlerts;
System.out.println("Clock thread initialised");
instructionsPerSecond = insPerSec;
}
And to your Clock:
private final BlockingQueue<Integer> edgeAlerts;
public Clock(double instructionsPerSecond, BlockingQueue<Integer> edgeAlerts)
{
this.edgeAlerts = edgeAlerts;
executionSpeed = instructionsPerSecond;
System.out.println("[Clock] Execution speed set to " + executionSpeed + "Hz. (" + timePeriod() + "s per instruction.)");
}
And your clock run becomes:
public void run()
{
toggleState();
System.out.println("System State: " + state);
edgeAlerts.offer(state);
}
Let me know if this works for you.
So here's my situation:
I got a few Threads that should do background work, ideally with a ThreadPool/ExecutorService and such
There are a lot of Runnables generated regularly that call one long method. They should be processed by the background workers.
The runnables have an order they should be executed in (approximately). The interesting thing is: that ordering is dynamic and might change at any time. So which runnable to take next should be decided as late as possible, directly before running it.
It should be possible to stop all currently working runnables. If this is not possible, they should be notified so that they discard their work once it's finished.
I don't really know how to approach this problem, and I'm not really familiar with multithreading and Java's APIs in that matter.
About the ordering
What I mean with approximately in order: if they get started in order, it will be good enough. Each Runnable does some work on a tile of a map. The idea is to sort the runnables in such a way, that tiles near the position where the used is looking at will be loaded first and then loading the surroundings. Note that therefore the order of execution might change at any time.
One solution is to put all the jobs that you want to process into a PriorityBlockingQueue. (This queue is automatically sorted either using the natural ordering of the queue items or by providing a Comparator). then the threads running within the ExecutorService should just take elements from the queue.
for example
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
public class PriorityQueueExample {
public static void main(String[] args) throws InterruptedException {
PriorityQueueExample priorityQueueExample = new PriorityQueueExample();
priorityQueueExample.doTheWork();
}
private void doTheWork() throws InterruptedException {
PriorityBlockingQueue<Customer> queue = new PriorityBlockingQueue<>(10, new CustomerComparator());
queue.add(new Customer("John", 5));
queue.add(new Customer("Maria", 2));
queue.add(new Customer("Ana", 1));
queue.add(new Customer("Pedro", 3));
while(queue.size() > 0){
System.out.println(queue.take());
}
}
}
class CustomerComparator implements Comparator<Customer> {
#Override
public int compare(Customer o1, Customer o2) {
return o1.getUrgency() - o2.getUrgency();
}
}
class Customer {
private String name;
private int urgency;
public Customer(String name, int urgency) {
this.name = name;
this.urgency = urgency;
}
public String getName() {
return name;
}
public int getUrgency() {
return urgency;
}
#Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", urgency=" + urgency +
'}';
}
}
1) Have your tiles implements Callable. You can have them return Callable too.
2) Determine which ones are position to be loaded first.
3) Pass them or their Callables into java.util.concurrent.ExecutorService.invokeAll.
4) Once invokeAll is returned get the next set of tiles adjacent to the previous ones and call java.util.concurrent.ExecutorService.invokeAll again.
5) Repeat step 4 if necessary.
you could also use a List to emulate a priority queue. For example:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListEmulateQueueExample {
public static void main(String[] args) throws InterruptedException {
ListEmulateQueueExample priorityQueueExample = new ListEmulateQueueExample();
priorityQueueExample.doTheWork();
}
/**
* uses a list to emulate a queue.
*/
private void doTheWork() {
List<Customer> customerList = Collections.synchronizedList(new ArrayList<>());
Customer johnCustomer = new Customer("John", 5);
Customer mariaCustomer = new Customer("Maria", 3);
Customer anaCustomer = new Customer("Ana", 1);
customerList.add(johnCustomer);
customerList.add(mariaCustomer);
customerList.add(anaCustomer);
CustomerComparator customerComparator = new CustomerComparator();
synchronized (customerList){
customerList.sort(customerComparator);
}
System.out.println(customerList.remove(0)); // Ana
johnCustomer.setUrgency(1);
synchronized (customerList){
customerList.sort(customerComparator);
}
System.out.println(customerList.remove(0)); // John
}
}
So, I finally got a way around this problem. It's not that beautiful and kind of a hack, but it works as intended.
The idea is: if every Runnable is stateless and does only call one method, it does not need to know the tile it should work on on creation. Instead, it will ask for a needed tile once it's started.
public class WorldRendererGL {
protected Map<Vector2i, RenderedRegion> regions = new ConcurrentHashMap<>();
protected Queue<RegionLoader> running = new ConcurrentLinkedQueue<>();
protected Set<RenderedRegion> todo = ConcurrentHashMap.newKeySet();
protected ExecutorService executor;
/** Recalculate everything */
public void invalidateTextures() {
//Abort current calculations
running.forEach(f -> f.invalid.set(true));
running.clear();
todo.addAll(regions.values());
for (int i = 0; i < regions.size(); i++) {
RegionLoader loader = new RegionLoader();
running.add(loader);
executor.submit(loader);
}
}
protected class RegionLoader implements Runnable {
/** Set this to true to nullify all calculations*/
final AtomicBoolean invalid = new AtomicBoolean(false);
#Override
public void run() {
try {
if (invalid.get())
return;
RenderedRegion region = null;
region = nextRegion(); // Get the correct work at runtime
if (region == null)
return;
BufferedImage texture = renderer.renderRegion(new RegionFile(region.region.regionFile));
if (!invalid.get()) {
region.texture = texture;
update.notifyObservers();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
protected RenderedRegion nextRegion() {
Comparator<RenderedRegion> comp = (a, b) -> /*...*/);
RenderedRegion min = null;
for (Iterator<RenderedRegion> it = todo.iterator(); it.hasNext();) {
RenderedRegion r = it.next();
if (min == null || comp.compare(min, r) > 0)
min = r;
}
todo.remove(min);
return min;
}
}
I'm a Java student and this is my attempt of implementing a StackExchange (there's a pusher thread and a popper thread, a single stack resource and two controlling Threads for the stack content and time passing).
I was hoping if someone could comment my code for improvements or errors\bad practices, even if the code seems to work.
The main reason of this program was to figure out how to control resource access in a multithreading environment.
I have concerns about the use of the ScheduledThreadPoolExecutor rather than locking(the stack), and my usage of synchronized in the StackExchange class methods(for accessing the stack), I would like to spawn free threads working on a dynamically locked resource. Any advice?
NB:"Format of magic numbers and syso's may be awful for testing porpuses
code here:
package examples;
import java.util.Random;
import java.util.Stack;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.JOptionPane;
public class StackExchange {
/*
* Two Threads playing with a stack, a timer and a controller for the stack that permits to exit
* */
public class Popper implements Runnable
{
StackExchange sEx;
public Popper(StackExchange sex)
{
this.sEx=sex;
}
#Override
public void run() {
System.out.println("Popper: popping!\t"+sEx.getPeek());
sEx.callTheStack(this, null);
}
}
public class Pusher implements Runnable
{
StackExchange sEx;
public Pusher(StackExchange sex)
{
sEx=sex;
}
#Override
public void run() {
System.out.println("Pusher: pushing!\t");
sEx.callTheStack(this, "Hi!");
}
}
public class StackController implements Runnable
{
private Stack<String> theStack;
public int waiting=5;
public StackController(Stack<String> theStack, String name) {
this.theStack = theStack;
Thread.currentThread().setName(name);
}
#Override
public void run()
{
Random rand = new Random();
waiting = rand.nextInt(10);
StringBuilder buffer = new StringBuilder();
int i=0;
for(String string: theStack)
{
buffer.append(string+"\n");
i++;
}
buffer.append("\nFound "+i+" elements\nIWillWait4:\t"+waiting);
System.out.println("\t\t\t\t\t\t\t\t"+Thread.currentThread().getName().toString()+" Says:" + buffer.toString());
if(i>1)
{
System.out.println("ERRER");
System.exit(0);
}
if(i==1 && JOptionPane.showConfirmDialog(null, "found 1 element\nWannaStop?")==0)
System.exit(0);
}
}
public class Timer implements Runnable{
#Override
public void run() {
StackExchange.time++;
System.out.println("Time Passed:\t"+StackExchange.time+" seconds");
}
}
/*
* implementation of the StackExchange class
* */
private Popper popper;
private Pusher pusher;
private StackController stackController;
private StackController secondSC;
private Timer timer;
static int time=0;
private Stack<String> stack;
public StackExchange()
{
timer = new Timer();
stack = new Stack<String>();
pusher = new Pusher(this);
popper = new Popper(this);
stackController = new StackController(this.getStack(), "FirstStackController");
}
public static void main(String[] args) {
StackExchange sex = new StackExchange();
sex.start();
System.out.println("Num of Threads:"+Thread.activeCount());
}
public void start()
{
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(5);
exec.scheduleAtFixedRate(timer, 0, 1, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(pusher, 0, 2, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(popper, 1, 2, TimeUnit.SECONDS);
exec.scheduleAtFixedRate(stackController, 0, stackController.waiting, TimeUnit.SECONDS);
}
public Stack<String >getStack()
{
return this.stack;
}
public void callTheStack(Object caller, String pushedString)
{
synchronized(this)
{
if(caller instanceof Popper)
stack.pop();
else if(caller instanceof Pusher)
stack.push(pushedString);
}
}
public String getPeek()
{
synchronized(this)
{
return stack.peek();
}
}
}
Things that might help:
Don't use java.util.Stack.
A more complete and consistent set of LIFO stack operations is
provided by the Deque interface and its implementations, which should
be used in preference to this class.
http://docs.oracle.com/javase/8/docs/api/java/util/Stack.html
Your nested subclasses of StackExchange are all inner classes so
that means they already have a reference to the containing
StackExchange instance
and its member stack instance, which should be final.
So don't pass them as parameters. This simplifies logic, maintenance,
and GC.
caller instanceof Popper this type of reflection is utterly
unnecessary and breaks object orientation.
You know that Object is too broad a type for callTheStack (weak
name). In fact, you know that the object will be a Runnable, but
more importantly, the Runnable should know what to do already.
Synchronization should be kept minimal to just the critical section that shares data and no more, shown below using the synchronized keyword
or to just the memory boundary, shown below using the volatile keyword
and member variables of a containing class are a great way to share data between threads within the class.
Example
public class StackExchange {
private final Deque<String> stack = new ArrayDeque<>();
private volatile boolean running;
private void consume(String item) {
// ...
}
private String obtain() {
// ...
}
private boolean getPermission() {
// ...
}
// getters, setters, ...
private final Runnable consumer = new Runnable() {
#Override
public void run() {
while (running) {
final String popped;
synchronized(stack) {
popped = stack.pollFirst();
}
consume(popped);
}
}
};
private final Runnable producer = new Runnable() {
#Override
public void run() {
while (running) {
final String pushing = obtain();
synchronized(stack) {
stack.offerFirst(pushing);
}
}
}
};
public static void main(String ... args) {
StackExchange exchange = new StackExchange();
exchange.setRunning(true);
new Thread(exchange.getConsumer()).start();
new Thread(exchange.getProducer()).start();
do {
} while (exchange.getPermission());
exchange.setRunning(false);
}
}
It's a good idea to declare member variables prior to member methods.
I put the Runnable code in anonymous classes to leave the code at the very edge of using lambdas.
The idea behind consume, obtain, and getPermission is to hint at how the code would interact with the business logic that doesn't know about threading. These could be implemented as callbacks or abstract methods.
One good thing about Deque is that it can easily be set up for a FIFO queue.
Just for fun, convert those Runnable instances into lambdas, and make the StackExchange class generic.
Hot question: what other subtypes of Deque<E> might suit, and what advantages or disadvantages would they have? What code changes might need to happen to accommodate them?
So I have a piece of code that I want to execute repeatedly. I get this part. The problem is that I want to execute the code at fixed intervals, but only a fixed number (in this case 1440) times.
Any ideas how I'd do that?
Here's the code:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Simulator {
public static int TICK = 10;
public static int NUM_OF_SERVERS = 3;
public static int LENGTH_OF_SIMULATION = 1440;
public static void main(String[] args) {
final MultiQueueControlSystem multiController = MultiQueueControlSystem.getInstance();
final SingleQueueControlSystem singleController = SingleQueueControlSystem.getInstance();
multiController.generateQueuesAndServers(NUM_OF_SERVERS);
singleController.generateQueuesAndServers(NUM_OF_SERVERS);
final ScheduledExecutorService ticker = Executors.newSingleThreadScheduledExecutor();
ticker.scheduleAtFixedRate(new Runnable() {
int currentTime = 0;
public void run() {
if(currentTime < LENGTH_OF_SIMULATION) {
currentTime = currentTime + 1;
} else {
ticker.shutdown();
return;
}
multiController.customerArrival();
multiController.allocateCustomersToServers();
multiController.removeFinishedCustomersFromServers();
singleController.customerArrival();
singleController.allocateCustomersToServers();
singleController.removeFinishedCustomersFromServers();
}
}, 1, TICK, TimeUnit.MILLISECONDS);
}
}
Consider giving your runnable a reference to the ScheduledExecutorService. Then instead of scheduling at a fixed rate, just schedule for future execution. Have the runnable instance keep tracker (through an AtomicInteger) how many times it has been executed. When it completes it's normal execution it can schedule itself for future execution. Once it has executed the desired number of times, it would not schedule itself again.
try this
Take any integer variable runCount (increment after every cycle) and service the object returned from scheduleAtFixedRate method
if(runCount == LENGTH_OF_SIMULATION ) {
service.cancel(false);
}
I just got simple problem, but it seems that I cant find a solution for it. Well the following code is part of open-source project, but this part is written by me from scratch.
Well, everything inside this "script" works well without problems except of one thing,
the int variable CB_State doesn't change after calling StartParticipation() method:
import java.util.Calendar;
import java.util.logging.Logger;
import com.l2jserver.gameserver.Announcements;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
public final class CastleBattle
{
private static Logger _log = Logger.getLogger("CastleBattle");
private static String htm_path = "data/scripts/l2dc/CastleBattle/";
public static int CB_State = 1; // 0 - Disabled, 1 - Not running, 2 - Participation start, 3 - Participation end, 4 - Running, 5 - Event ended
public CastleBattle()
{
CB_Init();
}
// Initialize Engine
private static void CB_Init()
{
if (CB_State == 1)
{
SetStartTime();
}
}
// Event Loop
public static void SetStartTime()
{
Calendar _nextTime = Calendar.getInstance();
int _m = _nextTime.get(Calendar.MINUTE);
int x = 1;
while (_m > 5)
{
_m -= 5;
x++;
}
_nextTime.set(Calendar.MINUTE, x * 5);
ThreadPoolManager.getInstance().scheduleGeneral(new CastleBattleLoop(), _nextTime.getTimeInMillis() - System.currentTimeMillis());
}
// Allow players to participate in the event
public static void StartParticipation()
{
CB_State = 2;
Announcements.getInstance().announceToAll("Castle Battle participation has started.");
_log.info("Castle Battle participation has started.");
}
// Player requests to join event via NPC
public static void CB_bypass(String _cmd, L2PcInstance _player)
{
if (_cmd.startsWith("InitHtmlRequest"))
{
if (CB_State == 0)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_Disabled.htm");
_player.sendPacket(_html);
}
if (CB_State == 1)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_NotRunning.htm");
_player.sendPacket(_html);
}
if (CB_State == 2)
{
NpcHtmlMessage _html = new NpcHtmlMessage(0);
_html.setFile("", htm_path + "CB_Participate.htm");
_player.sendPacket(_html);
}
}
}
public static void main(String[] args)
{
_log.info("# Castle Battle Engine #");
_log.info("Author : HyperByter");
_log.info("Version : Beta");
_log.info("Version : 3.7.2013");
new CastleBattle();
}
}
class CastleBattleLoop implements Runnable
{
#Override
public void run()
{
if (CastleBattle.CB_State == 1)
{
CastleBattle.StartParticipation();
}
}
}
So any suggestions how to fix this problem?
The method StartParticipation() is probably never called:
main() calls the constructor of CastleBattle
The CastleBattle constructor calls CB_Init()
CB_Init() calls SetStartTime()
SetStartTime() invokes this line:
ThreadPoolManager.getInstance().scheduleGeneral(new CastleBattleLoop(), _nextTime.getTimeInMillis() - System.currentTimeMillis());
after some whacky and indecipherable arithmetic on _nextTime, it's likely that the schedule interval is either very large, or perhaps negative, either of which may cause the Runnable CastleBattleLoop to never be started, in which case StartParticipation() would never be called.
I don't know what ThreadPoolManager does with strange input, but I would start by debugging what value is being passed into the scheduleGeneral() method and read the javadoc to see what effect such a value would have.
The class at the bottom is called CastleBattleLoop , but it does not contain anything loopy, so StartParticipation() gets called only once (if CB_State is 1 at that moment).
You should add something like
while(running){
if (CastleBattle.CB_State == 1)
{
CastleBattle.StartParticipation();
}
Thread.sleep(100);
}
StartParticipation() is being called inside a thread.
Check if you are trying to figure out its value even before actual change occurs.
[Not sure how are you figuring out the value of "CastleBattle.CB_State" in later part of the code]