Is Executors.newSingleThreadScheduledExecutor() applicable for multiple objects? - java

Im making a small game where space-ships fire in intervalls of x seconds.
In this method Im spawning lasers the enemies can fire. In order to time their shots
Im using
Executors.newSingleThreadScheduledExecutor();
but Im not sure if that´s right when there can be multiple enemy-space ships on the board at once.
(Since its using one thread and then waits x seconds before using that thread for that task again).
So summarized: is this the right way to time an event for multiple objects or is it only working for one object a a time.

There are some more performance optimized versions, but the aproach is fine for the beginning.
ScheduledFuture<?> future = s.scheduleAtFixedRate(shoot, 0, enemy.getRate(), TimeUnit.SECONDS);
Will be scheduled once impediatly, and then every getRate() seconds until you call future.cancel().
Only one shot is evaluated at a single moment, thats fine if the caclculation is rather quick, and you don't call Thread.sleep() in the Runnable.

Related

How to approach a Java event queue

Hello everyone and thanks for the time you dedicated in advance!
I have a problem I'm not sure how to approach in Java. Let's say I have a user interface that creates events that have to be "executed" in a specific time in the future, which may vary from a couple of minutes in the future to several days.
I have though of creating a class (let's say EventHandler) that implementa Runnable, and then a ConcurrentLinkedList that stores those instantiations ordered by the time they should be executed, from least in advance to most in advance. After that, a thread that peeks the queue, and If system time is greater than expected execution time, start the process.
Problem is, aside of concurrency problems associated with list, that the peek thread consumes CPU time. So I was wondering if there is a more elegant solution, considering there may be hundreds of events scheduled in a single second interval. Also, I'm using Hibernate with MongoDb to store stuff, if that affects at all.
Thank you!
EDIT: I'm open to all other solutions you may think of, as long as it solves the "queue events and execute them in the time they are set to"
A straightforward approach is to use ScheduledThreadPoolExecutor.
int corePoolSize = 1;// for sequential execution of tasks
// for parallel execution use Runtime.getRuntime().availableProcessors();
ScheduledThreadPoolExecutor executor = ScheduledThreadPoolExecutor(corePoolSize);
...
Runnable command1 = ...
executor.schedule(command1, 2, TimeUnit.MINUTES); // execute in couple of minutes
Runnable command2 = ...
executor.schedule(command2, 7, TimeUnit.DAYS); // execute in 7 days

Using less Timers

It doesn't really lag that much in my game but I know that I could reduce a lot of lag in my game by having less Timer's running. The game have multiple Timer's because it have one Timer that updates everything like the players location and all the obstacles then I have other Timer's that I use to remove the power ups that you could get.
For example I have one Timer that have it's initial delay set to 5000 and when it is runned one time (it will only run one time) it will remove a specific power up and the I have another Timer that have it's initial delay set to 20 000. How would I keep the different delay of each timer but still only using one or at least fever than I use now?
Is there anyway that I could use PriorityQueue or ScheduledThreadPoolExecutor to accomplish this? and if so how?
You would schedule tasks on the ScheduledThreadPoolExecutor, and then re-schedule them for a different delay if you want to run the same task again.
Another option is to use a DelayQueue to store the tasks you want to execute, and use a separate thread to take and execute runnables off of the queue. As with the ScheduledThreadPoolExecutor you'd have to put the runnables back on the queue with a new delay if you want them to run again.
The ScheduledThreadPoolExecutor lets you schedule tasks to continually run after a fixed delay, whereas the DelayQueue requires you to keep putting the task back on the queue after it's run.
Why would there be a timer that "updates everything"? Updating should always execute non-stop. (Unless you want to limit your game to constant FPS)
You really should consider abusing the "Game Loop":
While Game Is Running
Update()
Draw()
End While
If you don't want any lags in your game, you need to consider always updating player location, etc...
That said, when you update locations, etc... you need to make sure you make them relative to the time elapsed since last time Update() was executed.
If you're not constantly calling Update(), then you're going to have lags no matter what threading pattern you use.

Executing some code after a specific amount of time

I need to execute an action after a specific amount of time (for example 30 minutes after the app started up, if the app is still up).
What are my options and will it necessary means there's going to be one thread "lost" waiting for the 30 minutes to pass by?
Ideally, at program startup, I'd like to do something like the following (simplified on purpose) and then don't have to think about it anymore:
doIfStillUp( 30, new Runnable() {
....
});
So how should I go about implementing doIfStillUp(...)?
Should I use a TimerTask? The Executor framework?
Most importantly (it's for understanding purpose): does this mean there's going to be one thread lost idling for basically nothing during 30 minutes?
If there's going to be one thread "doing nothing", is this an issue? What if there are 10 000 threads (I'm being facetious here) "doing nothing"?
Note that I'm trying to understand the "big picture", not to solve a particular problem.
The Executor framework is a reasonable choice.
There's a schedule method that just takes a runnable and a delay time.
schedule(Runnable command,
long delay,
TimeUnit unit)
That's pretty straightforward. There won't necessarily be a thread blocked waiting on your task. You could use a ScheduledThreadPoolExecutor, as linked above that keeps X threads ready to run scheduled tasks.
You can imagine a data structure that holds the time at which a task should be run. A single thread can watch or set up these delays and can potentially watch thousands of them in a single thread. When the first time expires it'll run the task. Potentially using its own thread, potentially using 1 of X in the thread pool. When a new task is added or an existing task is finished it'll wait for the earliest time to arrive and then start the whole process again.
You should use a Timer. Its javadoc answers all your questions.
One thread is used for every timer, but the timer executes several tasks, sequentially. The timer tasks should be very short. If they aren't, consider using several timers.
Of course, the timer thread will be idle if it doesn't have any task to execute. An idle thread doesn't consume anything (or nearly anything), so I wouldn't worry about it. Anyway, you don't have many choices. 10000 threads doing nothing would of course be an issue, but that would mean that you instantiated one timer per task, which is wrong.
You can schedule task on java.util.Timer. For all timer tasks single timer thread will be created by java.util.Timer.
The builtin java timer is the straight away solution: http://download.oracle.com/javase/1,5.0/docs/api/java/util/Timer.html#schedule(java.util.TimerTask, long)

How do I make sure a Timer stays alive?

I have code that relies on a Timer staying alive and managing TimerTask. Usually TimersTasks will come and go and there will always be at least one TimerTask to keep the Timer alive, but every now and then all the TimerTasks will die and the Timer will die with it.
How would I keep Timer alive? Should I have one TimerTask in it at scheduled to fire at a far away date? That's what I'm leaning towards, but I want to hear what more experienced programer's ideas would be.
*It would also be nice if I could terminate all TimerTaks except for this one 'permanent' TimerTask.
Sorry if none of this makes much sense, or if I'm thinking of Timers and TimerTasks all wrong. I'm brand new to Java and all programming.
This sounds backwards. The Timer is the thing that manages the tasks. The TimerTask is the thing that is getting managed. You create a timer, you tell it to schedule the timertask, which can be singular or continuous (e.g. you can set the task to run every hour for as long as your JVM is running). It will run until it has no more tasks.
From the docs:
After the last live reference to a Timer object goes away and all
outstanding tasks have completed execution, the timer's task execution
thread terminates gracefully (and becomes subject to garbage
collection).

Constantly checking a port without a while loop

In a program (Java) I'm making I need to check for a specific pin in the parallel port. Whenever that pin goes from logical 0 to 1 (a positive edge clock) I have to read the data on the port and save it. This happens about every 10ms but can vary a little.
To do this I made a separate thread with a while loop that is constantly checking the port, but this makes the processor go nuts and I know it's because of the while loop. My question is, how can I constantly scan the port without using a processor intensive while loop? The program doesn't know precisely when a pin change will happen, only that it happens around every 10ms.
Fire a thread which is scheduled to execute the given Runnable at a fixed rate. You can use Timer#scheduleAtFixedRate() or ScheduledExecutorService#scheduleAtFixedRate() for this. The last one is preferred.
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new PortScanner(), 0, 10, TimeUnit.MILLISECONDS); // Run every 10 ms.
Where PortScanner can look like this:
public class PortScanner implements Runnable {
#Override
public void run() {
// Scan port here.
}
}
Don't forget to call scheduler.shutdown() at the moment your application exits, else the thread may hang.
There might be a better solution, but worst case you could just Thread.sleep for 1-2ms every iteration of the while loop.
It is really tricky to catch hardware interrupts when your code is not running as a part of operating system. What you can do is to put Thread.Sleep ( 5 ). This will sleep for 10 milliseconds, and will let the other threads run or just keep CPU idle and cool. Having 5 ms delay should be enough to ensure won't miss any clock ticks.
This would work when your clock is alternating between 10 ms high and 10 ms low. For other patterns you have to adjust the parameter accordingly.

Categories

Resources