I want to limit the number of calls for a method to 5 within 10 seconds. There will be calls to the method from different threads. After that time has passed, I want the counter for the method to be resetted so for the next 10 seconds, 5 more calls can be made and this will go on. What could be a good way to do this?
Thanks
Maybe use a Semaphore and a Timer to release tokens:
public class RateLimitedTask() {
private final Timer timer = new Timer();
private final Semaphore semaphore;
private final Runnable task;
public RateLimitedTask(
final Runnable task,
final int limit,
final int delay
) {
this.task = task;
semaphore = new Semaphore(limit);
timer.schedule(new TimerTask() {
#Override
public void run() {
semaphore.release(limit);
}
}, delay*1000, delay*1000);
}
public void run() throws InterruptedException {
semaphore.acquire();
task.run();
}
}
Related
I have a method that will be called all the time.
After calling, a job(runnable) will be generated and submitted to the thread pool. The timeout time of each job is different, depending on the incoming parameters.
Now I want to monitor whether each job can end within the timeout time when it starts to execute. What should I do?
Note that timeout is from the beginning of execution to the end of execution, not from the time of delivery to the thread pool to the end of task execution. Because of this, I don't think future #get (timeout) can be used, am I right?.
And acceptJob should not block, it has to return immediately after submitting the job(maybe some other logic, but not block).
ExecutorService pool = Executors.newFixedThreadPool(10);
public void acceptNewJob(Map<String, Object> params) {
// timeout from params
int timeoutInMs = (int) params.get("timeoutInMs");
pool.submit(new Runnable() {
#Override
public void run() {
// generate a job by params
// if this job execute timeout, need alarm
}
});
}
How about wrapping every runnable and use a Timer to check the runnable's status when the timeout period expires.
public void acceptNewJob(Map<String, Object> params) {
// timeout from params
int timeoutInMs = (int) params.get("timeoutInMs");
MonitoredRunnable runnable = new MonitoredRunnable(new Runnable() {
#Override
public void run() {
// generate a job by params
// if this job execute timeout, need alarm
}
}, timeoutInMs);
pool.submit(runnable);
}
// Or use ScheduledThreadPoolExecutor
private Timer timer = new Timer();
public class MonitoredRunnable implements Runnable {
private volatile int state = READY;
public static final int READY = 0;
public static final int RUNNING = 1;
public static final int COMPLETE = 0;
private Runnable task;
private int timeoutInMs;
public MonitoredRunnable(Runnable task, int timeoutInMs) {
this.task = task;
this.timeoutInMs = timeoutInMs;
}
#Override
public void run() {
state = RUNNING;
startMonitor(this);
task.run();
state = COMPLETE;
}
private void startMonitor(MonitoredRunnable runnable) {
timer.schedule(new TimerTask() {
#Override
public void run() {
try {
if (runnable.state != COMPLETE) {
System.out.println("Job timeout.");
// alarm
}
} catch (Exception e) {
//
}
}
}, runnable.timeoutInMs);
}
I am trying to execute a task periodically. For example:
class MyTimerTask implements TimerTask
{
public void run() {
// Some actions to perform
}
Timer cleaner = new Timer(true);
cleaner.scheduleAtFixedRate(new MyTimerTask(), 0, PURGE_INTERVAL);
}
However, the run method is executing only once. But if I put the first time delay as 10 seconds, then the run method doesn't execute even once.
Example:
cleaner.scheduleAtFixedRate(new MyTimerTask(), 10, PURGE_INTERVAL);
This sounds like an issue with time units to me. Ensure that you're converting to milliseconds correctly.
The easiest way to do this is to use Java's TimeUnit.
Timer cleaner = new Timer(true);
cleaner.scheduleAtFixedRate(new MyTimerTask(),
TimeUnit.SECONDS.toMillis(10),
TimeUnit.SECONDS.toMillis(30));
It could also be caused by the Timer being started in daemon mode. If all your main method does is set up the timer and then return the timer will never execute since it's the last remaining thread and because it's a daemon thread the JVM will exit.
To fix this either make the timer thread not a daemon (i.e. pass false in the constructor) or make the main thread wait for user input before exiting.
Here's an example using both of the above:
public class TimerDemo extends TimerTask {
public void run() {
System.out.printf("Time is now %s%n", LocalTime.now());
}
public static void main(String[] args) throws IOException {
Timer timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerDemo(),
TimeUnit.SECONDS.toMillis(5),
TimeUnit.SECONDS.toMillis(10));
System.out.printf("Program started at %s%n", LocalTime.now());
System.out.println("Press enter to exit");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
// Wait for user to press enter
reader.readLine();
}
System.out.println("Bye!");
}
}
And output of running it:
Program started at 14:49:42.207
Press enter to exit
Time is now 14:49:46.800
Time is now 14:49:56.799
Time is now 14:50:06.799
Time is now 14:50:16.799
Time is now 14:50:26.799
[I pressed 'enter']
Bye!
Process finished with exit code 0
I had a hard time figuring out exactly what is your problem, so this might not be exactly what you are asking for, but this solution might fit you:
public class MyTimerTask implements Runnable {
private static final TimeUnit timeUnit = TimeUnit.SECONDS;
private final ScheduledExecutorService scheduler;
private final int period = 10;
public static void main(String[] args) {
new MyTimerTask();
}
public MyTimerTask() {
scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(this, period, period, timeUnit);
}
#Override
public void run() {
// This will run every 10 seconds
System.out.println("Ran...");
}
}
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
}
}
}
I have some type of task for example in a loop with same method but different arguments,
I need to execute these tasks in one after another in some intervals,
and all this activity need to be execute in again and again in a particular schedule,
e.g. let say I have a method called
public void GetData(String tablename){
}
so first time I will provide table1 then table2 then table3.....
similar to for loop but need some interval in between,
and same above all execution need to execute in each 10 min,
sample code I have implemented as
final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
final Runnable runner = new Runnable() {
public void run() {
getData(String table);
}
};
final ScheduledFuture<?> taskHandle =
scheduler.scheduleAtFixedRate(runner, 1, 10, SECONDS);
its working fine for one table for need help and best way to implement for multiple tables.
tryjava.util.Timer to schedule a task to execute
public class ReminderBeep {
Toolkit toolkit;
Timer timer;
public ReminderBeep(int seconds) {
toolkit = Toolkit.getDefaultToolkit();
timer = new Timer();
timer.schedule(new RemindTask(), seconds * 1000);
}
class RemindTask extends TimerTask {
public void run() {
System.out.println("Time's up!");
toolkit.beep();
//timer.cancel(); //Not necessary because we call System.exit
System.exit(0); //Stops the AWT thread (and everything else)
}
}
public static void main(String args[]) {
System.out.println("About to schedule task.");
new ReminderBeep(5);
System.out.println("Task scheduled.");
}
}
You can just use Thread.sleep() in your loop (if it's not on the main thread). Something like this (the code is not tested so may contain errors):
ExecutorService executorService = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
public void run() {
getData(String table);
}
Thread.sleep(10000);
}
How to set the Thread priority of a Timer in java? This is the code I have found in the project that I am working on, and I do not think that it is working:
public static Timer createNamedTimer(boolean isDaemon,
final String threadName, final int priority) {
Timer timer = new Timer(isDaemon);
timer.schedule(new TimerTask() {
public void run() {
Thread.currentThread().setName("TimerThread: " + threadName);
Thread.currentThread().setPriority(priority);
}
}, 0);
return timer;
}
AFAIK for timer the only way you can change priority is the way you are doing it.
If you need a better option you can use the ThreadFactory for creating the threads and setting their priority.
class SimpleThreadFactory implements ThreadFactory {
private int threadPriority;
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setPriority(threadPriority);
return t;
}
}
Then you can pass the factory to the Executors framework of Java for doing what you want, IMHO this will be a much better approach.
Why do I say it would be a better approach?
The Timer class's JavaDoc mentions ScheduledThreadPoolExecutor and notes, that this class is effectively a more versatile replacement for the Timer/TimerTask combination
The suggested solution won't likely work for tasks that are repeated more than once, because between invocations another task that shared the same thread may have adjusted the priority to something else. Therefore, for repeating tasks you must set the priority at execution time, every time. This potential issue exists w/or w/o the new Executors framework.
One solution is to create a wrapper class that does prep work for you to ensure consistency. For example:
AnyClass.java:
private static void exampleUsage()
{
try { launchHighPriorityTask(() -> System.out.println("What a fancy task.")).join(); }
catch (Throwable ignored) {}
}
private static Thread launchMaxPriorityTask(Runnable task)
{
final Thread customThread = new Thread(new Task("MaxPriority", Thread.MAX_PRIORITY, task));
customThread.start();
return customThread;
}
Task.java:
public class Task implements Runnable
{
private final String name;
private final int priority;
private final Runnable task;
public Task(String name, int priority, Runnable task)
{
if (null == task) throw new NullPointerException("no task provided");
this.name = name; this.priority = priority; this.task = task;
}
/**
* run() is made final here to prevent any deriving classes
* accidentally ruining the expected behavior
*/
#Override public final void run()
{
final Thread thread = Thread.currentThread();
// cache the current state to restore settings and be polite
final String prevName = thread.getName();
final int prevPriority = thread.getPriority();
// set our thread's config
thread.setName(name);
thread.setPriority(priority);
try { task.run(); } catch (Throwable ignored) {}
// restore previous thread config
thread.setPriority(prevPriority);
thread.setName(prevName);
}
}
This is naturally a minimalist example of what can be accomplished with this sort of setup.