How can i cycle between different game status messages in JDA? - java

I am trying to make the bot show it's server count, which gets updated every 20 seconds of so!
I have tried to put it in a loop after an await ready event:
public void onReady(ReadyEvent event) {
while (true) {
TimeUnit.SECONDS.sleep(20)
event.JDA().getPresence().setGame(Game.watching(event.getJDA().getGuilds().size() + "servers"));
}
}
This has succeeded in displaying the amount of servers it joined but this stopped any other code from being run.
So how can I do this without the rest of the program being ignored?

You should try setting an interval and doing the update on it
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
event.JDA().getPresence().setGame(Game.watching(event.getJDA().getGuilds().size() + "servers"));
};
executor.scheduleWithFixedDelay(task, 0, 20,TimeUnit.SECONDS);
or using Timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
event.JDA().getPresence().setGame(Game.watching(event.getJDA().getGuilds().size() + "servers"));
}
}, 0, 20000 );
setting it inside a while(true) makes it stop there, because it extecutes on the main thread whitout creating a new one.

Related

in java the after timer.cancel(), got exctpion

Trying do some debouncing, the use case is that client may send multiple requests to server in short interval unnecessarily. The requests are all the same but response is different at the time of the server processing, so the last response is the one to use.
With following code if do not always create a new timer, after timer.cancel(), the timer.schedule() will crash with "Timer already cancelled.".
Can't the timer be reused?
Is there better way to do the debouncing without using timer?
private Timer debouncerTimer = new Timer();
synchronized void debounceRequest() {
debouncerTimer.cancel();
//debouncerTimer = new Timer(); //<== without this one it crashes with IllegalStateException("Timer already cancelled.")
debouncerTimer.schedule(new TimerTask() {
#Override
public void run() {
doSendRequest();
}
}, 150);
}
A facility for threads to schedule tasks for future execution in a
background thread. Tasks may be scheduled for one-time execution, or
for repeated execution at regular intervals.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Timer.html
Here is an example using ScheduledExecutorService that could work:
private ScheduledExecutorService debouncer = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> scheduledRequest;
synchronized void debounceRequest() {
if (scheduledRequest != null) {
scheduledRequest.cancel(false);
}
scheduledRequest = debouncer.scheduleWithFixedDelay(this::doSendRequest, 0, 150, TimeUnit.MILLISECONDS);
}
private void doSendRequest() {
//Send request stuff here
}

Java - How could I create a timer to run in the background of a program, while still allowing the user to interact? [duplicate]

I have a thread which is in charge of doing some processes. I want make it so that these processing would be done every 3 seconds. I've used the code below but when the thread starts, nothing happens.
I assumed that when I define a task for my timer it automatically execute the ScheduledTask within time interval but it doesn't do anything at all.
What am I missing?
class temperatureUp extends Thread
{
#Override
public void run()
{
TimerTask increaseTemperature = new TimerTask(){
public void run() {
try {
//do the processing
} catch (InterruptedException ex) {}
}
};
Timer increaserTimer = new Timer("MyTimer");
increaserTimer.schedule(increaseTemperature, 3000);
}
};
A few errors in your code snippet:
You extend the Thread class, which is not really good practice
You have a Timer within a Thread? That doesnt make sense as the a Timer runs on its own Thread.
You should rather (when/where necessary), implement a Runnable see here for a short example, however I cannot see the need for both a Thread and Timer in the snippet you gave.
Please see the below example of a working Timer which will simply increment the counter by one each time it is called (every 3seconds):
import java.util.Timer;
import java.util.TimerTask;
public class Test {
static int counter = 0;
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
System.out.println("TimerTask executing counter is: " + counter);
counter++;//increments the counter
}
};
Timer timer = new Timer("MyTimer");//create a new Timer
timer.scheduleAtFixedRate(timerTask, 30, 3000);//this line starts the timer at the same time its executed
}
}
Addendum:
I did a short example of incorporating a Thread into the mix. So now the TimerTask will merely increment counter by 1 every 3 seconds, and the Thread will display counters value sleeping for 1 seconds every time it checks counter (it will terminate itself and the timer after counter==3):
import java.util.Timer;
import java.util.TimerTask;
public class Test {
static int counter = 0;
static Timer timer;
public static void main(String[] args) {
//create timer task to increment counter
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
// System.out.println("TimerTask executing counter is: " + counter);
counter++;
}
};
//create thread to print counter value
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
System.out.println("Thread reading counter is: " + counter);
if (counter == 3) {
System.out.println("Counter has reached 3 now will terminate");
timer.cancel();//end the timer
break;//end this loop
}
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
timer = new Timer("MyTimer");//create a new timer
timer.scheduleAtFixedRate(timerTask, 30, 3000);//start timer in 30ms to increment counter
t.start();//start thread to display counter
}
}
import java.util.Timer;
import java.util.TimerTask;
public class ThreadTimer extends TimerTask{
static int counter = 0;
public static void main(String [] args) {
Timer timer = new Timer("MyTimer");
timer.scheduleAtFixedRate(new ThreadTimer(), 30, 3000);
}
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("TimerTask executing counter is: " + counter);
counter++;
}
}
In order to do something every three seconds you should use scheduleAtFixedRate (see javadoc).
However your code really does nothing because you create a thread in which you start a timer just before the thread's run stops (there is nothing more to do). When the timer (which is a single shoot one) triggers, there is no thread to interrupt (run finished before).
class temperatureUp extends Thread
{
#Override
public void run()
{
TimerTask increaseTemperature = new TimerTask(){
public void run() {
try {
//do the processing
} catch (InterruptedException ex) {}
}
};
Timer increaserTimer = new Timer("MyTimer");
//start a 3 seconds timer 10ms later
increaserTimer.scheduleAtFixedRate(increaseTemperature, 3000, 10);
while(true) {
//give it some time to see timer triggering
doSomethingMeaningful();
}
}
I think the method you've used has the signature schedule(TimerTask task, long delay) . So in effect you're just delaying the start time of the ONLY execution.
To schedule it to run every 3 seconds you need to go with this method schedule(TimerTask task, long delay, long period) where the third param is used to give the period interval.
You can refer the Timer class definition here to be of further help
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html
Timer & TimerTask are legacy
The Timer & TimerTask classes are now legacy. To run code at a certain time, or to run code repeatedly, use a scheduled executor service.
To quote the Timer class Javadoc:
Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.
Executor framework
In modern Java, we use the Executors framework rather than directly addressing the Thread class.
Define your task as a Runnable or Callable. You can use compact lambda syntax seen below. Or you can use conventional syntax to define a class implementing the Runnable (or Callable) interface.
Ask a ScheduledExecutorService object to execute your Runnable object’s code every so often.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() ;
Runnable task = () -> {
System.out.println( "Doing my thing at: " + Instant.now() );
};
long initialDelay = 0L ;
long period = 3L ;
TimeUnit timeUnit = TimeUnit.SECONDS ;
scheduledExecutorService.submit( task , initialDelay, period , timeUnit ) ;
…
scheduledExecutorService.shutdown() ; // Stops any more tasks from being scheduled.
scheduledExecutorService.awaitTermination() ; // Waits until all currently running tasks are done/failed/canceled.
Notice that we are not directly managing any Thread objects in the code above. Managing threads is the job of the executor service.
Tips:
Always shutdown your executor service gracefully when no longer needed, or when your app exits. Otherwise the backing thread pool may continue indefinitely like a zombie 🧟‍♂️.
Consider wrapping your task's working code in a try-catch. Any uncaught exception or error reaching the scheduled executor service results in silently halting the further scheduling of any more runs.

how to make a thread that loops a temporized action in android

I want,in my mainactivity,to start a thread that does some stuff every x seconds.
is this aproach correct?
taken from my oncreate method:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(5000);
do stuff
};
thread.start();
if it's relevant it starts a videoplayer and checks its buffer every 5 seconds.
You can create flexible and effective timer using Java's ExecutorService:
// create executor that consists of 1 thread
final ExecutorService e = Executors.newScheduledThreadPool(1);
// schedule it to execute every 5000 ms starting from now
((ScheduledExecutorService) e).scheduleAtFixedRate(new Runnable(){
#Override
public void run() {
// your repeating task
}
}, 0, 5000, TimeUnit.MILLISECONDS);
This approach is more flexible and, if Java docs don't lie, more precise since it is independent on system clock changes.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html

using Timer class - How can I make a scheduled Job started as scheduled even if the prior job isn't finished?

Without using Quartz, is there any option for Timer class or workaround to start scheduled jobs even if the previous job is not finished?
Here's sample code.
Job Scheduled for every 1 sec
public static void main(String[] args) {
Timer timer = new Timer();
Calendar date = Calendar.getInstance();
timer.scheduleAtFixedRate(new UnitTest(timer), date.getTime(), 1000);
}
Job Performed
Each job has 2 second delay
public void run() {
count++;
int a = count; // to see which job is started and ended.
System.out.println(this.now("HH:mm:ssSSS")+"- start "+count);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(this.now("HH:mm:ssSSS")+"- end "+a);
}
Result - if the previous job is not finished, then the next job is not started.
12:14:21946 - start 1
12:14:23965 - end 1
12:14:23965 - start 2
12:14:25966 - end 2
12:14:25967 - start 3
12:14:27968 - end 3
12:14:27968 - start 4
12:14:29969 - end 4
12:14:29970 - start 5
12:14:31970 - end 5
12:14:31971 - start 6
12:14:33972 - end 6
How can I add this option for Timer class?
Quartz - Concurrent Option from http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html
By default, Quartz Jobs are stateless, resulting in the possibility of jobs interfering with each other. If you specify two triggers for the same JobDetail, it might be possible that before the first job has finished, the second one will start. If JobDetail classes implement the Stateful interface, this won't happen. The second job will not start before the first one has finished. To make jobs resulting from the MethodInvokingJobDetailFactoryBean non-concurrent, set the concurrent flag to false.
EDITED SAMPLE CODE
public class TEST01 {
Timer timerTEST01 = new Timer();
public String[] start()
{
try
{
timerTEST01.scheduleAtFixedRate(new TimerTask() {
public void run() {
Runnable r = new Runnable() {
public void run() {
//DoWork
}
};
Thread t = new Thread(r);
t.start();
}
}, date.getTime(), 1000*60);
return new String[]{"true", "Good Job!"};
}
catch(Exception e){}
finally{}
}
}
Instead of running the code directly at the timer, when the timer calls your method, spawn a new thread (or use a thread poll) to execute your task:
public void run() {
Runnable r = new Runnable() {
public void run() {
count++;
int a = count; // to see which job is started and ended.
System.out.println(this.now("HH:mm:ssSSS")+"- start "+count);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(this.now("HH:mm:ssSSS")+"- end "+a);
}
};
Thread t = new Thread(r);
t.start();
}
This will guarantee that every single job executes at the given time even if the previous one hasn't executed.
Also, make sure your code works inside an anonymous inner class, that count++ probably isn't going to work.
TimerTask timertask=new TimerTask(
public void run(){
//code
}
);
Timer timer = new Timer();
//Use timer to execute and set time limits for execution

Java Timer

I'm trying to use a timer to schedule a recurring event in an application. However, I want to be able to adjust the period at which the event fires in real time (according to the users input).
For example:
public class HelperTimer extends TimerTask
{
private Timer timer;
//Default of 15 second between updates
private int secondsToDelay = 15;
public void setPeriod(int seconds)
{
this.secondsToDelay = seconds;
long delay = 1000; // 1 second
long period = 1000*secondsToDelay; // seconds
if (timer != null)
{
timer.cancel();
}
System.out.println(timer);
timer = new Timer();
System.out.println(timer);
timer.schedule(this, delay, period);
}
public int getPeriod()
{
return this.secondsToDelay;
}
}
I then start a new instance of this class and call its set period function. However, when I do that, I get an Illegal state exception. You can see the System.out.println(timer); in there because I'm checking, and yep sure enough, they are two different timers... so why am I getting an IllegalStateException when I try to run a schedule call on a brand new Timer instance!?!?!?!
java.util.Timer#c55e36
java.util.Timer#9664a1
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Task already scheduled or cancelled
at java.util.Timer.sched(Unknown Source)
at java.util.Timer.schedule(Unknown Source)
at HelperTimer.setPeriod(HelperTimer.java:38)
You can't reuse a TimerTask as you're doing here.
Relevant porition of Timer:
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
//Right here's your problem.
// state is package-private, declared in TimerTask
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
You'll need to refactor your code so that you create a new TimerTask, rather than re-using one.
It seems odd to me to have a TimerTask with its own Timer inside it. Bad design. I'd totally separate the two and have the TimerTask implementation be handed off to a Timer, and put all that logic about fiddling with the period inside another class that provides an interface for doing so. Let that class instantiate the Timer and TimerTask and send them off to do their work.
You can use ScheduledExecutorService, which allows you to schedule the same task multiple times without using scheduleAtFixedRate. Here's a quick example:
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
Runnable timerTask = new Runnable() {
#Override
public void run() {
// Do something
System.out.println("Task run!");
// Schedule again
executorService.schedule(this, 15, TimeUnit.SECONDS);
}
};
// Schedule
executorService.schedule(timerTask, 15, TimeUnit.SECONDS);
In this exmaple, "Executed...." will be printed after 4 seconds of delay. After that, it will be printed continuously every 3 seconds:
import java.util.*;
class TimeSetting {
public static void main(String[] args) {
Timer t = new Timer();
TimerTask time = new TimerTask() {
public void run() {
System.out.println("Executed......");
}
};
t.scheduleAtFixedRate(time, 4000, 3000);
/*
* The task will be started after 4 secs and
* for every 3 seconds the task will be continuously
* executed.....
*/
}
}

Categories

Resources