The below code details an id read when a serial event happens,an id is generated every fews seconds when the device is powered on(Serial Event), and no serial data is received when it is powered off .problem is i need a url call to be sent once when the id is received and once when not visible(powered down).
I believe im close but cannot seem to get it right.I would be very grateful if someone could help with this and how to set flags and scheduler to achieve the above case and possibly explain where im going wrong.
int numberOfEmptyIds = 0;
int maxNumberOfAttempts = 5;
boolean urlSent = false;
long timeoutInMillis = 10000; // let's say 10000 millis, equivalent to 10 seconds
Timer timer = null;
public void connect(String portName) throws Exception {
...
scheduleTimer();
}
public void serialEvent(SerialPortEvent evt) {
if(evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
while(in.read(buffer) > -1) {
String asHexStr = DatatypeConverter.printHexBinary(buffer);
if(asHexStr.contains("FB1")) {
scheduleTimer();
numberOfEmptyIds = 0;
} else {
numberOfEmtyIds++;
if(numberOfEmptyIds == maxNumberOfAttempts && !urlSent) {
// send the url here
}
}
}
} catch (IOException ex) {
// Log the exception here
}
}
}
private void scheduleTimer() {
timer = new Timer("Timeout");
TimerTask task = new TimerTask() {
#Override
public void run() {
if(!urlSent) {
// send the url here
}
}
};
timer.schedule(task, timeoutInMillis);
}
Problem is i need a url call to be sent once when the id is received
and once when not visible(powered down).
The second part is done by the timer, if no data arrives to the serial port then the scheduled task will sent the URL (if not sent yet). In my answer to your previous question I forgot to cancel the timer when the task is re-scheduled :
private void scheduleTimer() {
if(timer != null) {
timer.cancel();
}
timer = new Timer("Timeout");
TimerTask task = new TimerTask() {
#Override
public void run() {
if(!urlSent) {
// send the url here
}
}
};
timer.schedule(task, timeoutInMillis);
}
This way there would be a single scheduled task. From Timer.cancel() javadoc:
Terminates this timer, discarding any currently scheduled tasks. Does
not interfere with a currently executing task (if it exists). Once a
timer has been terminated, its execution thread terminates gracefully,
and no more tasks may be scheduled on it.
Note that calling this method from within the run method of a timer
task that was invoked by this timer absolutely guarantees that the
ongoing task execution is the last task execution that will ever be
performed by this timer.
About the first part you can manage it with boolean flags just like urlSent. If you need to send the URL just a single time then you can have a flag for the URL sent by ID arriving and another flag for URL sent due no data (or empty ID's) received.
Edit
Based on the flow-chart you've posted here and shown below:
Enter description here http://dl6.fileswap.com/storage_previews/02112014/54cd147697479d29c43c530b93d5fa83/52fe9168/aW1hZ2UvanBlZw%3D%3D/4cf59787af56f18847df6235cdc20816.jpg
You maybe can change your current approach using Timer.scheduleAtFixedRate() method to check at a fixed rate of time a if the serial port stops reading the ID. As you need to send the ID received notification just once then you may set urlSent flag to true when this URL is efectively sent. Also I think you can get rid of check if the received data doesn't contain the expected ID. Something like this:
boolean urlSent = false;
long lastIdArrivalTime = 0;
long timeTolerance = 60000;
long timeoutInMillis = 300000; // 5 minutes
Timer timer = null;
public void connect(String portName) throws Exception {
...
scheduleTimer();
}
public void serialEvent(SerialPortEvent evt) {
if(evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
while(in.read(buffer) > -1) {
String asHexStr = DatatypeConverter.printHexBinary(buffer);
if(asHexStr.contains("FB100000010F0801")) {
lastIdArrivalTime = System.currentTimeMillis();
if(!urlSent) {
// send the URL notifying the ID
urlSent = true; // next time url will not be sent
}
}
}
} catch (IOException ex) {
// Log the exception here
}
}
}
private void scheduleTimer() {
timer = new Timer("Timeout");
TimerTask task = new TimerTask() {
#Override
public void run() {
long currentTime = System.currentTimeMillis();
if((currentTime - lastIdArrivalTime) >= timeTolerance) {
// sent the URL notifying the device is off
urlSent = false; // this way the next ID arrival will be notified
}
}
};
timer.scheduleAtFixedRate(task, timeoutInMillis, timeoutInMillis);
}
Some notes:
The timer is scheduled just once this time because it will execute the task every 5 minutes. If you need to shut down the connection don't forget to call timer.cancel() method.
The variable lastIdArrivalTime holds the last time in milliseconds when an ID arrives.
The variable timeTolerance is a max time tolerance to assume the connection is down. As you've said the device sends the ID at a seconds fixed period, so if spent 1 minute since the last ID arrival then you can assume the connection is down (or device is off).
Some hints on your code available here:
TimerTask implements Runnable interface and is intended to be used using Timer class which will create a separate thread to execute this task when the scheduled time comes, so don't use TimerTask in a new thread.
Don't mess with
Threads
unless you know exactly what are you doing. It's extremely easy make a
mistake and mess the things up.
Related
How to set a Timer, say for 2 minutes, to try to connect to a Database then throw exception if there is any issue in connection?
So the first part of the answer is how to do what the subject asks as this was how I initially interpreted it and a few people seemed to find helpful. The question was since clarified and I've extended the answer to address that.
Setting a timer
First you need to create a Timer (I'm using the java.util version here):
import java.util.Timer;
..
Timer timer = new Timer();
To run the task once you would do:
timer.schedule(new TimerTask() {
#Override
public void run() {
// Your database code here
}
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);
To have the task repeat after the duration you would do:
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Your database code here
}
}, 2*60*1000, 2*60*1000);
// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);
Making a task timeout
To specifically do what the clarified question asks, that is attempting to perform a task for a given period of time, you could do the following:
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Runnable r = new Runnable() {
#Override
public void run() {
// Database task
}
};
Future<?> f = service.submit(r);
f.get(2, TimeUnit.MINUTES); // attempt the task for two minutes
}
catch (final InterruptedException e) {
// The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
// Took too long!
}
catch (final ExecutionException e) {
// An exception from within the Runnable task
}
finally {
service.shutdown();
}
This will execute normally with exceptions if the task completes within 2 minutes. If it runs longer than that, the TimeoutException will be throw.
One issue is that although you'll get a TimeoutException after the two minutes, the task will actually continue to run, although presumably a database or network connection will eventually time out and throw an exception in the thread. But be aware it could consume resources until that happens.
Use this
long startTime = System.currentTimeMillis();
long elapsedTime = 0L.
while (elapsedTime < 2*60*1000) {
//perform db poll/check
elapsedTime = (new Date()).getTime() - startTime;
}
//Throw your exception
Ok, I think I understand your problem now. You can use a Future to try to do something and then timeout after a bit if nothing has happened.
E.g.:
FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
#Override
public Void call() throws Exception {
// Do DB stuff
return null;
}
});
Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);
try {
task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
// Handle your exception
}
new java.util.Timer().schedule(new TimerTask(){
#Override
public void run() {
System.out.println("Executed...");
//your code here
//1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly
}
},1000*5,1000*5);
[Android] if someone looking to implement timer on android using java.
you need use UI thread like this to perform operations.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
ActivityName.this.runOnUiThread(new Runnable(){
#Override
public void run() {
// do something
}
});
}
}, 2000));
I need to simulate a widget that shows purchases in real time.
To increase statistics, I want to supercharge real purchases with fake data, that needs to be emit in random interval.
All the events (real and fake ones) go to the message channel and get processed and then send to frontend.
So I need to come up with some service, that I can control (run and stop)
public class FakeDataGenerator {
private boolean run;
private Queue queue;
public void run() {
run = true;
while(run) {
queue.push(generateFakeOne())
TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(1, 30));
}
}
public void stop() {
run = false;
}
private Purchase generateFakeOne() {
// ... some faking logic
}
}
generator.stop();
where generator.run(); will start emitting events with random interval, and generator.stop(); will allow me to stop it any time
Is there any tool to accomplish such task? I'm not happy with using an infinite loop.
If you are using spring-boot why don't try using just #Scheduled(fixedDelay = 1000) annotation example
Example
#Scheduled(fixedDelay = 1000)
public void scheduleFixedDelayTask() {
System.out.println(
"Fixed delay task - " + System.currentTimeMillis() / 1000);
}
Use some of Spring Executor and give it a task to execute. You can control it by the executor reference
I'm making an input stream rate meter. It is basically a service that exposes a request stream call and counts how many messages per second it can handle.
As the client is totally async when it comes to sending messages, I use the ClientCallStreamObserver to start sending messages just when the stream is ready, to avoid memory overflow.
The client code looks like this:
public static void main(String[] args) throws Exception {
ManagedChannel channel = ManagedChannelBuilder.forAddress("server", 4242).usePlaintext(true).build();
ServerGrpc.ServerStub asyncStub = ServerGrpc.newStub(channel);
StreamObserver<MarketDataOuterClass.Trade> inputStream = asyncStub.reportNewTradeStream(new StreamObserver<Empty>() {
#Override
public void onNext(Empty empty) {
}
#Override
public void onError(Throwable throwable) {
logger.info("on error response stream");
}
#Override
public void onCompleted() {
logger.info("on completed response stream");
}
});
final ClientCallStreamObserver<MarketDataOuterClass.Trade> clientCallObserver = (ClientCallStreamObserver<MarketDataOuterClass.Trade>) inputStream;
while (!clientCallObserver.isReady()) {
Thread.sleep(2000);
logger.info("stream not ready yet");
}
counter.setLastTic(System.nanoTime());
while (true) {
counter.inc();
if (counter.getCounter() % 15000 == 0 ) {
long now = System.nanoTime();
double rate = (double) NANOSEC_TO_SEC * counter.getCounter() / (now - counter.getLastTic());
logger.info("rate: " + rate + " msgs per sec");
counter.clear();
counter.setLastTic(now);
}
inputStream.onNext(createRandomTrade());
}
}
My observation loop over isReady is never ending.
OBS: I'm using kubernetes cluster to serve my test, the server is receiving the call and returning a StreamObserver implementation.
isReady should eventually return true, as long as the RPC doesn't error/complete immediately. But the code is not observing flow control properly.
After each call to onNext() to send a request isReady() could begin returning false. Your while (true) loop should instead have the isReady() check at the beginning of each iteration.
Instead of polling, it is better to call serverCallObserver.setOnReadyHandler(yourRunnable) to be notified when the call is ready to send. Note that you should still check isReady() within yourRunnable as there can be spurious/out-of-date notifications.
I'm working on a Minecraft Bukkit plugin, I know how to handle events and everything, but I'm not sure how to do this. I haven't actually written the code yet so here's a basic example of what I want to do:
public void playerDead() {
runCommand(commandHere)
//Wait 2 minutes.
runCommand(otherCommandHere
}
I just need the part to wait two minutes. Everything else is covered.
EDIT2: Seems I need to reset the delay to the beginning if someone else dies while it's going. Any suggestions?
Since I see you want to perform your action after the player has died. Then for sure you don't want to halt the main Thread with Thread.sleep(x);
What you can do is create a cooldown for the player that passed away.
public Map<String, Long> cooldown = new HashMap<String, Long>();
Long time = cooldown.get(player.getName());
if(time - System.currentTimeMillis() > 10*1000)
cooldown.put(player.getName(), System.currentTimeMillis());
else
int remains = (int)Math.floor(10 - System.currentTimeMillis());
Code reference here.
Or you can create your task to run like this:
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
{
public void playerDied()
{
// Your code here.
}
}, <delay in ticks>);
Get a reference to your plugin and pass it as the parameter plugin. Or if you are lazy just write it inside the plugin and pass it this.
You should use the BukkitScheduler provided by Bukkit.
You have to save the BukkitTask object returned by the Scheduler.runTaskLater(...) method to use it later.
Every time playerDead() is called, you can reset the delay by cancelling and restarting the task.
BukkitTask task;
public void playerDead() {
// Command here
if (task != null) {
task.cancel();
}
task = getServer().getScheduler().runTaskLater(Plugin, new Task(), 2400L);
}
public class Task extends BukkitRunnable {
#Override
public void run() {
// Other command here
task = null;
}
}
You may try like this:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
runCommand(commandHere);
}
}, 120000);
I'm new to the #Schedule annotations in J2EE6
I want to run a job using EJB 3.x with Glassfish 3.1.
The javax.ejb.Schedule seems to be a good choice for us, so we could think of our custom time as something like:
#Singleton
public class CustomTimer {
#EJB
SettingsFacade settingsFacade;
#Schedule(second="someSecondParameter", minute="someMinuteParameter",hour="someHourParameter", persistent=false)
public void executeTimer(){
//Code executing something against database using the settingsFacade
}
}
Here, we want the parameters to be got from database, so they are changed every month. Any clean solution for this?
#Singleton
#Startup
public class ScheduleTimerService {
#Resource private TimerService timerService;
public void setTimerService(TimerService timerService) {this.timerService = timerService; }
#PostConstruct
private void postConstruct() {
timerService.createCalendarTimer(createSchedule());
}
#Timeout
public void timerTimeout(Timer timer) {
Add your code here to be called when scheduling is reached...
in this example: 01h:30m every day ;-)
}
private ScheduleExpression createSchedule(){
ScheduleExpression expression = new ScheduleExpression();
expression.dayOfWeek("Sun,Mon,Tue,Wed,Thu,Fri,Sat");
expression.hour("01");
expression.minute("30");
return expression;
}
}
No, there is no solution with #Schedule, because annotation attributes in general should be compile time constants.
When more flexibility is needed, programmatic timers can be used.
Also then polling database for changed configuration and removing existing and creating new timers must be implemented.
Well You need to created Two Scheduler
One Scheduler will run to update data from Database
Based On that You Can created Other Scheduler.
But for this Need to do it some what programmatic.
You also can see EJB Timers for the same what will help you in this case. which is also annotation based.
There is a simple way of doing this. I wanted to something that called a process every day but, the job itself should be done randomly over the same day. I managed to do that by adding a simple thread worker to run after the EJB timer service has been called. Then I would put it to sleep for a random amount of time during that day.
The following code is an example of a service that wakes up every 1 minute and waits for a thread to finish.
#Schedule(minute = "*/1", hour = "*", persistent = false)
public void runEveryMinute() throws InterruptedException {
log.log(Level.INFO, "Scheduling for every minute .. now it's: " + new Date().toString());
// Delay, in milliseconds before we interrupt adding a follower thread
//we can therefore garantee that it runs every day
long patience = 1000 * 5;
threadMessage("Starting forever alone no more thread");
long startTime = System.currentTimeMillis();
Thread t = new Thread(new MessageLoop());
t.start();
threadMessage("Waiting for new thread to finish");
// loop until MessageLoop thread exits
while (t.isAlive()) {
threadMessage("Still waiting...");
// Wait maximum of 1 second for MessageLoop thread to finish.
t.join(1000);
if (((System.currentTimeMillis() - startTime) > patience)
&& t.isAlive()) {
threadMessage("Tired of waiting! Adding new followers now!");
t.interrupt();
// Shouldn't be long now -- wait indefinitely
t.join();
}
}
threadMessage("Finally! You are not alone anymore!");
}
// Display a message, preceded by
// the name of the current thread
static void threadMessage(String message) {
String threadName = Thread.currentThread().getName();
System.out.format("%s: %s%n", threadName, message);
}
private static class MessageLoop implements Runnable {
public void run() {
String importantInfo[] = {
"A kid will eat ivy too"
};
try {
for (int i = 0;
i < importantInfo.length;
i++) {
// Pause for 4 seconds
int max = 10;
int min = 2;
int randomTimer = 0 + (int) (Math.random() * ((max - min) + 1));
Thread.sleep(randomTimer * 1000);
// Print a message
threadMessage(importantInfo[i]);
}
} catch (InterruptedException e) {
threadMessage("Patience is not a virtue! Thread stopping for now!");
}
}
}