Listen to certain events (object listener) - java

Let's say I have a simple code which increments variable "counter" by 1, every 5 seconds. I would like to stop timer, when "counter" reaches 5. I would like to use object listener for this (listens to certain events). Is this possible?
public class CallMe{
static int counter = 0;
public static void main(String[] args) {
// This code increments counter variable by 1, every 5 seconds.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
counter++;
System.out.println(counter);
}
}, 1000, 5000);
}
}

It is very much possible indeed. There are two interfaces in java.util Observer and Observable. You can use these interfaces to implement the Observer Pattern. Just google with "Observable Examples" and you will find plenty of resources.
All you need to do is implement this class as Observable and create another class as Observer. When your counter reach 5, all you need to do is to call the notifyObservers() method and it will fire an event for all the registered observers.

You need to implement an Observer pattern for your variable.
The class containing your counter should maintain a collection of very class that wants to be notified about what counter is. Then when counter reaches 5, you send the notification to all the listeners.
#Override
public void run() {
counter++;
System.out.println(counter);
if(counter == 5) {
notify();
}
}
private void notify() {
for(ChangeListener l : listeners) {
l.stateChanged(new ChangeEvent(counter));
}
}
some other class:
class Obs implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
System.out.println(e);
}
}

You can call the cancel method on your TimerTask :
#Override
public void run() {
counter++;
if(counter == 5) {
this.cancel();
}
System.out.println(counter);
}

Related

Java terminate a timertask using data from the task itself

I have got the basics of how Timer and TimerTask work in Java. I have a situation where I need to spawn a task that will run periodically at fixed intervals to retrieve some data from database. And it needs to be terminated based on the value of the retrieved data (the data itself is being updated by other processes)
Here is what I came up with so far.
public class MyTimerTask extends TimerTask {
private int count = 0;
#Override
public void run() {
count++;
System.out.println(" Print a line" + new java.util.Date() + count);
}
public int getCount() {
return count;
}
}
And a class with a main method like so. For now I have trivially used a 15 second sleep to control how long the timerTask runs.
public class ClassWithMain {
public static void main(String[] args) {
System.out.println("Main started at " + new java.util.Date());
MyTimerTask timerTask = new MyTimerTask();
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(timerTask, 0, 5*10*100);
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main done"+ new java.util.Date());
}
The MyTimerTask class will become more complex with the database service calls and so on.
What I want to be able to do is, in the main class, interrogate a value returned by timerTask to dictate when to invoke timer.cancel() and terminate the process. Right now if I try to use the count property of MyTimerTask it doesn't work. So when I tried adding these lines in ClassWithMain
if (timerTask.getCount() == 5){
timer.cancel();
}
it didn't stop the process.
So I'd like any direction on how I might be able to accomplish what I'm trying to do.
private volatile int count = 0; It is better to use 'volatile'.
try this in ClassWithMain:
for(;;) {
if (timerTask.getCount() == 5) {
timer.cancel();
break;
} else{
Thread.yield();
}
}

How do you use ticks in bukkit?

I understand ticks, 20 ticks to a second etc. but i don't get the syntax. Can someone explain to me the steps of making something with ticks? I have a fireball move here as an example of something i need ticks for; after each time it does the effect, i need it to wait like, 2 ticks. I've looked at other examples but i really don't understand the syntax
#EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
List<Block> targets = player.getLineOfSight((Set)null, 30);
for (Block targetblock : targets){
Location target = targetblock.getLocation();
player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
}
}
}
I need to know how to add a delay to a loop, timing is really important in this plugin i'm trying to make and i just need to know the syntax.
Anyone help?
To make a timer, you can use
Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
//code
}
},ticksToWait);//run code in run() after ticksToWait ticks
So, if you wanted to wait 2 ticks before running the function shootFireball(), for example, you could use
Bukkit.getServer().getScheduler().runTaskLater(plugin, new Runnable(){
public void run(){
shootFireball();
}
},2L);//run code in run() after 2 ticks
plugin will be the instance of your Main class (the one that extends JavaPlugin). So, for example, your onEnable and onDisable functions in your Main class could look like this:
public static Main that; //in your case "plugin" would be "Main.that"
#Override
public void onEnable(){
that = this; //Main.that is now equal to this class
}
#Override
public void onDisable(){
that = null; //Set to null to prevent memory leaks
}
So, your code could look something like this:
#EventHandler
public void onPlayerInteractBlockFireBall(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (player.getItemInHand().getType() == Material.MAGMA_CREAM){
List<Block> targets = player.getLineOfSight((Set)null, 30);
for (int i = 0; i < targets.size(); i++){
//call the spawnFlames with "i * 2" ticks, because
//every time "i" is incremented, there is a new target block
//which means we should wait 2 more ticks than the previous
//iteration before running the task
spawnFlames(player, targets.get(i), i * 2);
}
}
}
public void spawnFlames(final Player player, final Block target, final long ticks){
Bukkit.getServer().getScheduler().runTaskLater(Main.that, new Runnable(){
public void run(){
Location target = targetblock.getLocation();
player.getWorld().playEffect(target, Effect.MOBSPAWNER_FLAMES,5);
}
},ticks);
//run code in run() after "ticks" ticks
//"ticks" will be equal to "i * 2" from
//the onPlayerInteractBlockFireBall() method
}
You will start using Scheduler Programming.
Look carefully at this part of the tutorial.
You need a repeating task for this purpose:
First, create a class that extends BukkitRunnable.
Then override the Runnable.run() method: it will be called once per iteration.
Now start the task with BukkitRunnable.runTaskTimer(Plugin, long, long).
You can stop it at any time using BukkitRunnable.cancel().
You could implement the feature like this:
List<Block> blocks; // The target blocks
BukkitRunnable task = new MagmaEffect(blocks);
Plugin main; // The unique instance of the main class
task.runTaskTimer(main, 0L, 2L);
public class MagmaEffect extends BukkitRunnable {
private List<Block> blocks;
public MagmaEffect(List<Block> blocks) {
this.blocks = blocks;
}
private int index;
#Override
public void run() {
Block block = blocks.get(index);
block.getWorld().playEffect(block.getLocation(), Effect.MOBSPAWNER_FLAMES, 5);
index++;
if (index == blocks.size()) {
cancel();
}
}
}

Is there a code to check if a timer is running?

I have a game where I am scheduling a timer. I have this CoresManager file:
package com.rs.cores;
import java.util.Timer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public final class CoresManager {
protected static volatile boolean shutdown;
public static WorldThread worldThread;
public static ExecutorService serverWorkerChannelExecutor;
public static ExecutorService serverBossChannelExecutor;
public static Timer fastExecutor;
public static ScheduledExecutorService slowExecutor;
public static int serverWorkersCount;
public static void init() {
worldThread = new WorldThread();
int availableProcessors = Runtime.getRuntime().availableProcessors();
serverWorkersCount = availableProcessors >= 6 ? availableProcessors - (availableProcessors >= 12 ? 7 : 5) : 1;
serverWorkerChannelExecutor = availableProcessors >= 6 ? Executors
.newFixedThreadPool(availableProcessors - (availableProcessors >= 12 ? 7 : 5),
new DecoderThreadFactory()) : Executors.newSingleThreadExecutor(new DecoderThreadFactory());
serverBossChannelExecutor = Executors
.newSingleThreadExecutor(new DecoderThreadFactory());
fastExecutor = new Timer("Fast Executor");
slowExecutor = availableProcessors >= 6 ? Executors.newScheduledThreadPool(availableProcessors >= 12 ? 4 : 2,
new SlowThreadFactory()) : Executors
.newSingleThreadScheduledExecutor(new SlowThreadFactory());
worldThread.start();
}
public static void shutdown() {
serverWorkerChannelExecutor.shutdown();
serverBossChannelExecutor.shutdown();
fastExecutor.cancel();
slowExecutor.shutdown();
shutdown = true;
}
private CoresManager() {
}
}
I am using this inside the game:
private void startTimer() {
CoresManager.fastExecutor.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (timer == 0 || timer < 1) {
player.sm("Your timer has ended! The NPCs will no longer spawn.");
timer = 0;
this.cancel();
exitInstance();
return;
}
timer--;
timerchecker = true;
seconds = timer % 60;
player.setTimer(timer);
minutes = TimeUnit.SECONDS.toMinutes(timer);
}
}, 0, 1000);
}
The CoresManager Timer stops running if the player logs out AND the server gets rebooted. To make it run again, I added a code to make it do startTimer() again once you log back in. However, since the timer still runs if the server didn't log out, the timer starts running twice. The Timer starts getting subtracted by 2, or more, depending on how many times you log out and in. I figure that it would fix if there was a code to determine if the timer is already running. Is there a way to do this? Please help!
I don't see anything in the documentation that provides for checking the status on a TimerTask object (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/TimerTask.html) so one option would be to extend TimerTask and create your own class. Instead of using an anonymous TimerTask, you could create something along the lines of:
public class CoresTimerTask extends TimerTask {
private boolean hasStarted = false;
#Overrides
public void run() {
this.hasStarted = true;
//rest of run logic here...
}
public boolean hasRunStarted() {
return this.hasStarted;
}
}
and just maintain a reference to this CoresTimerTask object, which you then pass into startTimer(). You can then later check this object via hasRunStarted.
public long scheduledExecutionTime()
Returns the scheduled execution time of the most recent actual execution of this task. (If this method is invoked while task execution is in progress, the return value is the scheduled execution time of the ongoing task The return value is undefined if the task has yet to commence its first execution.
This method is typically not used in conjunction with fixed-delay execution repeating tasks, as their scheduled execution times are allowed to drift over time, and so are not terribly significant.
first thing periodically running tasks need set/reset state flag
second (when i look at examples) it is better to seal this type of class
but if someone insist to have such methods
public abstract class NonInterruptableTask extends TimerTask {
protected boolean isDone = false;
public boolean isDone() {return isDone;}
protected abstract void doTaskWork();
#Override
public void run() {
isDone = false;
doTaskWork();
isDone = true;
}
}
usage:
TimerTask myTask = new NonInterruptableTask() {
#Override
public void doTaskWork() {
//job here
}
};
you could also declare a boolean state called like "timerstate" or whatever and make it by default to be false. whenever you start a timer you could change this boolean to true and you'd be able to keep track of the timer.
public boolean timerstate;
public Timer t1;
// some code goes here to do whatever you want
if(timerstate == true) {
t1.cancel();
t1.purge();
t1 = new Timer();
} else{
t1.schedule(new TimerTask() {
#Override
public void run() {
timerstate = true;
//rest of code for the timer goes here
}
}
}

How to gather frequent update/redraw/layout/refresh operations in SWT/Swing?

I am doing some frequent operations, which require GUI refresh (adding some children to a control).
I can't control the moment when the entire bunch of additions finished, so I can't do update/redraw/layout/refresh at the end and need do it each step.
Simultaneously I need nod do it very frequent, because user need not see each change.
Also each update/redraw/layout/refresh slows the process.
So, I need to decide whether to update/redraw/layout/refresh by time.
I wrote the following general class for SWT, but similar also applicable to Swing.
Is it's logic complete and correct? Especially, will the check delayedMap.get(doRun) == timer work correctly in multithreading? It's purpose is to cancel delayed operation in the case if entering the invokeOnceDelayed() method is occured between enterings into TimerTask.run() and inner synchronized block?
public class SWTUtilities {
private static HashMap<Runnable, Timer> delayedMap = new HashMap<Runnable, Timer>();
public static void invokeLater(Runnable doRun) {
Display.getDefault().asyncExec(doRun);
}
public static void invokeAndWait(Runnable doRun) {
Display.getDefault().syncExec(doRun);
}
public static synchronized void invokeOnceDelayed(final Runnable doRun, long delay) {
final Timer timer = new Timer(true);
Timer oldTimer = delayedMap.put(doRun, timer);
if( oldTimer != null ) {
oldTimer.cancel();
}
timer.schedule(new TimerTask() {
#Override
public void run() {
synchronized(SWTUtilities.class) {
if( delayedMap.get(doRun) == timer ) {
invokeLater(doRun);
}
}
}}, delay);
}
}
You can probably just delegate to Display.timerExec for the implementation of invokeOnceDelayed() method.

Passing variable into methods (Java)

I'm new to Java, and I have a problem. I've copied some code off a tutorial for Android, and now I want to pass an integer variable into the method run(), so I can increment it for each loop and then catch it outside the background Thread. How would I do that?
int gg= 0;
Thread background = new Thread(new Runnable() {
public void run() {
try {
while (pBarDialog.getProgress() <= 100) {
Thread.sleep(100);
gg++; // the increment here
progressHandler.sendMessage(progressHandler
.obtainMessage());
}
if (pBarDialog.getProgress() == 100) {
pBarDialog.dismiss();
}
} catch (java.lang.InterruptedException e) {
// if something fails do something smart
}
}
});
//catch gg here
You can't specify argument to the run() method. You may declare int variable as field and use it in inner classes.
public class TestActivity extends Activity
{
private volatile int no;
.....
}
EDIT: (Suggestion from #alf) You can use volatile modifier with field so changed value can be seen immediately by all other threads.
Have your own class and pass the counter using its constructor, I haven't tried that, but I would start with something like that:
class MyThread implements Runnable {
private volatile int counter;
public MyThread( int counter ) {
this.counter = counter;
}
public void run() {
...
}
public getCounter() {
return counter;
}
}
MyThread mt = new MyThread( 10 );
Thread t = new Thread( mt );
t.start();
// after some time
t.getCounter();
private volatile int gg;
public void myMethod() {
Thread background = new Thread(new Runnable() {
#Override
public void run() {
try {
while (pBarDialog.getProgress() <= 100) {
Thread.sleep(100);
gg++; // the increment here
progressHandler.sendMessage(progressHandler.obtainMessage());
}
if (pBarDialog.getProgress() == 100) {
pBarDialog.dismiss();
}
} catch (java.lang.InterruptedException e) {
// if something fails do something smart
}
}
});
System.out.println(gg);
}
If I were you, I'd be looking into AtomicInteger, namely the incrementAndGet() method.
Making gg a field will indeed give the thread access to gg, and volatile will make the changes visible, but since your intentions are not clear, I cannot be sure that you don't have other threads incrementing the same value: you don't have atomicity, so as soon as you have more than one thread doing gg++, you're likely to get wrong results.

Categories