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);
}
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.
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;
I have the following case to model
the program starts by querying the DB per received parameters and understanding the amount of tasks to be run.
Threads queue with some fixed max threads is defined to execute the tasks. Each task starts a flow that can have different configuration and can take different time. Once a tasks completes, each has a configurable sleep time.
Once a task sleeps, it cannot block a spot on the execution queue. The execution queue must continue with tasks that are ready to execute
I find it hard to code for some reason (mainly due to the last requirement)
Any help will be appreciated
Thanks
This is lengthy, but straight-forward code for illustration of scheduled resubmitter, which I haven't tested :)
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.*;
interface Repeatable {
boolean shouldBeRepeated();
/**
* #return how long to sleep
*/
long delayBeforeRepeat();
/**
* #return "initial" state of this task instance, so this state can be resubmitted for repeated execution
*/
BusinessTask reset();
}
/**
* Whatever suits your business logic
*/
interface BusinessTask extends Callable<Repeatable> {
}
class BusinessTaskCompletionData {
final BusinessTask businessTask;
/**
* Timestamp when this task should be resubmitted
*/
final long nextSubmitTime;
BusinessTaskCompletionData(BusinessTask businessTask, long nextSubmitTime) {
this.businessTask = businessTask;
this.nextSubmitTime = nextSubmitTime;
}
}
class TaskResusltsConsumer implements Runnable {
private final CompletionService<Repeatable> completionService;
private final Deque<BusinessTaskCompletionData> completedTasks;
TaskResusltsConsumer(ExecutorService executor, Deque<BusinessTaskCompletionData> completedTasks) {
this.completedTasks = completedTasks;
completionService = new ExecutorCompletionService<>(executor);
}
#Override
public void run() {
while (true) {
try {
Future<Repeatable> completedBusinessTask = completionService.take();
Repeatable repeatable = completedBusinessTask.get();
if (repeatable.shouldBeRepeated()) {
completedTasks.add(new BusinessTaskCompletionData(repeatable.reset(),
System.currentTimeMillis() + repeatable.delayBeforeRepeat()));
}
} catch (ExecutionException | InterruptedException ie) {
// handle somehow
}
}
}
}
class TasksSupplier implements Runnable {
private final Deque<BusinessTaskCompletionData> completedTasks;
private final ExecutorService executor;
TasksSupplier(Deque<BusinessTaskCompletionData> completedTasks, ExecutorService executor) {
this.completedTasks = completedTasks;
this.executor = executor;
}
#Override
public void run() {
while (true) {
BusinessTask t = getTaskSomehow();
executor.submit(getTaskSomehow());
}
}
private BusinessTask getTaskSomehow() {
// implement
return null;
}
}
/**
* Actual implementation of logic to obtain 'initial state' of task to repeat and repeat schedule
*/
class BusinessData implements Repeatable {
// whatever
}
public class SOTest {
public static void main(String[] args) {
final LinkedList<BusinessTaskCompletionData> tasksToRepeat = new LinkedList<>();
// workers pool
final ExecutorService workersPool = Executors.newFixedThreadPool(10);
// controllers pool: 1 thread for supplier, the other for results consumer
final ExecutorService controllersPool = Executors.newFixedThreadPool(2);
controllersPool.submit(new TasksSupplier(tasksToRepeat, workersPool));
controllersPool.submit(new TaskResusltsConsumer(workersPool, tasksToRepeat));
// resubmitter scheduled pool
ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
long now = System.currentTimeMillis();
Iterator<BusinessTaskCompletionData> it = tasksToRepeat.iterator();
while (it.hasNext()) {
BusinessTaskCompletionData data = it.next();
if (data.nextSubmitTime >= now) {
workersPool.submit(data.businessTask);
it.remove();
}
}
}
},
// initial delay of 1 sec
1000,
// periodic delay of 1 sec
1000,
TimeUnit.MILLISECONDS
);
}
}
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]
Class A
{
long x;
method1()
{
x = current time in millisecs;
}
task()//want to run this after (x+30) time
}
I need to run task() after (x+30) . x could be varying. if method1 is called, then task is scheduled to run after 30 from current time, but within that 30 timeperiod if method1 is called again then i want to cancel the previous task call and want to schedule a new call to task after 30 sec from current time. How should i create a scheduler or task of this type?
Went through the scheduledthreadpoolexecutor API but didn't find a scheduler of this type.
You're asking 2 questions:
1. How can I schedule a task with an arbitrary delay?
You can use one of the schedule methods on a java.util.concurrent.ScheduledThreadPoolExecutor
int delay = System.currentTimeMillis + 30;
myScheduledExecutor.schedule(myTask, delay, TimeUnit.MILLISECONDS);
2. How can I cancel an already running task?
You cancel a task by calling cancel on the Future that is returned from the schedule method you called.
if (!future.isDone()){
future.cancel(true);
}
future = myScheduledExecutor.schedule(myTask, delay, TimeUnit.MILLISECONDS);
I would record the time method1 is called and I would check every second whether the method was called 30 seconds ago. This way it will only perform the task when there has been no call for 30 seconds.
Use java.util.Timer and pass a callback into the TimerTask to schedule the next run. TimerTask can be cancelled with cancel method if needed. e.g.
package test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTaskDemo {
private Timer timer = new Timer();
private MyTimerTask nextTask = null;
private interface Callback {
public void scheduleNext(long delay);
}
Callback callback = new Callback() {
#Override
public void scheduleNext(long delay) {
nextTask = new MyTimerTask(this);
timer.schedule(nextTask, delay);
}
};
public static class MyTimerTask extends TimerTask {
Callback callback;
public MyTimerTask(Callback callback) {
this.callback = callback;
}
#Override
public void run() {
// You task code
int delay = 1000;
callback.scheduleNext(delay);
};
}
public void start() {
nextTask = new MyTimerTask(callback);
timer.schedule(nextTask, 1000);
}
public static void main(String[] args) {
new TimerTaskDemo().start();
}
}
Why don't you model your requirement using the Timer class of the JDK. Based on your requirements you will be scheduling the task in the timer as required.
I think the easiest way to do what you need is the following. Class B is the calling class.
class A {
public void runAfterDelay(long timeToWait) throws InterruptedException {
Thread.sleep(timeToWait);
task();
}
}
class B {
public static void main(String[] args) throws InterruptedException {
A a = new A();
// run after 30 seconds
a.runAfterDelay(30000);
}
}
Class A
{
$x;
function method1()
{
$time = microtime(true);
}
sleep($time + 30);
task()//want to run this after (x+30) time
}