how to execute a task after varying time - java

Class A
{
long x;
method1()
{
x = current time in millisecs;
}
task()//want to run this after (x+30) time
}
I need to run task() after (x+30) . x could be varying. if method1 is called, then task is scheduled to run after 30 from current time, but within that 30 timeperiod if method1 is called again then i want to cancel the previous task call and want to schedule a new call to task after 30 sec from current time. How should i create a scheduler or task of this type?
Went through the scheduledthreadpoolexecutor API but didn't find a scheduler of this type.

You're asking 2 questions:
1. How can I schedule a task with an arbitrary delay?
You can use one of the schedule methods on a java.util.concurrent.ScheduledThreadPoolExecutor
int delay = System.currentTimeMillis + 30;
myScheduledExecutor.schedule(myTask, delay, TimeUnit.MILLISECONDS);
2. How can I cancel an already running task?
You cancel a task by calling cancel on the Future that is returned from the schedule method you called.
if (!future.isDone()){
future.cancel(true);
}
future = myScheduledExecutor.schedule(myTask, delay, TimeUnit.MILLISECONDS);

I would record the time method1 is called and I would check every second whether the method was called 30 seconds ago. This way it will only perform the task when there has been no call for 30 seconds.

Use java.util.Timer and pass a callback into the TimerTask to schedule the next run. TimerTask can be cancelled with cancel method if needed. e.g.
package test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTaskDemo {
private Timer timer = new Timer();
private MyTimerTask nextTask = null;
private interface Callback {
public void scheduleNext(long delay);
}
Callback callback = new Callback() {
#Override
public void scheduleNext(long delay) {
nextTask = new MyTimerTask(this);
timer.schedule(nextTask, delay);
}
};
public static class MyTimerTask extends TimerTask {
Callback callback;
public MyTimerTask(Callback callback) {
this.callback = callback;
}
#Override
public void run() {
// You task code
int delay = 1000;
callback.scheduleNext(delay);
};
}
public void start() {
nextTask = new MyTimerTask(callback);
timer.schedule(nextTask, 1000);
}
public static void main(String[] args) {
new TimerTaskDemo().start();
}
}

Why don't you model your requirement using the Timer class of the JDK. Based on your requirements you will be scheduling the task in the timer as required.

I think the easiest way to do what you need is the following. Class B is the calling class.
class A {
public void runAfterDelay(long timeToWait) throws InterruptedException {
Thread.sleep(timeToWait);
task();
}
}
class B {
public static void main(String[] args) throws InterruptedException {
A a = new A();
// run after 30 seconds
a.runAfterDelay(30000);
}
}

Class A
{
$x;
function method1()
{
$time = microtime(true);
}
sleep($time + 30);
task()//want to run this after (x+30) time
}

Related

Call function every x time without blocking the GUI Java

I have a class caled ItemGUI which is handling everything related with the user interface. The user, is able to add some links, which are the items, so when he inserts a link and clicks on the ADD button, it should create a new object of the class Item and start running a function called getPrice(), something like that:
Item newItem = new Item(newItemField.getText());
// should also be added to a list of items which should be in the ItemGUI class
newItem.getPrice()
This should be done after clicking the add button. Then I print the item to the table. The problem is that the method getPrice() should run every 5 seconds without blocking my GUI, so I should implement Threads.
My question is: how can I be able to implement a thread that runs that function (for each item in the list) every 5 seconds until I click on a stop button? I was thinking about using the observer-observable classes with a clock that notifies its observers every 5 seconds. Will this be the best option?
Also, will I be able to retrieve the item variables from the ItemGUI class?
Thanks!
Update
The clearest solution by MadProgrammer's suggestion is to use swing Timers, like this:
protected javax.swing.Timer refresherTimer = null;
protected void stopRefreshing() {
if (refresherTimer != null) {
refresherTimer.stop();
refresherTimer = null;
}
}
protected void startRefreshing() {
stopRefreshing();
refresherTimer = new Timer(500, e -> {
newItem.getPrice()
});
refresherTimer.start();
}
public void onStartButtonClicked() {
Item newItem = new Item(newItemField.getText());
// here newItem should be added to a list of items which should be in the ItemGUI class
startRefreshing();
}
public void onStopButtonClicked() {
stopRefreshing();
}
Original answer
It would be nice to have some utility named e.g. GuiTimer which would make your task as easy as:
protected GuiThread.Task refresherTask = null;
protected void cancelRefreshing() {
if (refresherTask != null) {
refresherTask.cancel();
refresherTask = null;
}
}
public void onStartButtonClicked() {
Item newItem = new Item(newItemField.getText());
// should also be added to a list of items which should be in the ItemGUI class
cancelRefreshing();
refresherTask = GuiThread.scheduleAtFixedRate(() -> {
newItem.getPrice()
}, 0, 5, TimeUnit.SECONDS);
}
public void onStopButtonClicked() {
cancelRefreshing();
}
The problem with regular timers is that they invoke the callback function on their own thread, not on the gui thread, so it requires the developer to ensure proper threading. Unfortunately the builtin java EventQueue does not support dispatching delayed tasks.
For this reason I like to have the following utility called GuiTimer, which will act as a pure gui-threaded timer:
public class GuiTimer {
public static final ScheduledThreadPoolExecutor executor =
new ScheduledThreadPoolExecutor(1);
public static interface Task {
public void cancel();
}
private static class CancelStateTask implements Task {
public volatile boolean canceled = false;
#Override
public void cancel() {
this.canceled = true;
}
}
public static Task schedule(final Runnable action) {
CancelStateTask task = new CancelStateTask();
EventQueue.invokeLater(() -> {
if (!task.canceled)
action.run();
});
return task;
}
public static Task schedule(final Runnable command, long delay,
TimeUnit unit) {
ScheduledFuture<?> future = executor.schedule(
() -> EventQueue.invokeLater(command), delay, unit);
return () -> future.cancel(false);
}
public static Task scheduleAtFixedRate(Runnable command,
long initialDelay, long period, TimeUnit unit) {
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
() -> EventQueue.invokeLater(command), initialDelay,
period, unit);
return () -> future.cancel(false);
}
public static Task scheduleWithFixedDelay(Runnable command,
long initialDelay, long delay, TimeUnit unit) {
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
() -> EventQueue.invokeLater(command), initialDelay, delay,
unit);
return () -> future.cancel(false);
}
public static void shutdown() {
executor.shutdown();
}
}
First off, I'm in no way sure how this should be done, but I think I have a suggestion for how you could make it work.
In a project I'm working on at the moment I use ExecutorService to handle my thread pool. I have to mention here, that I started working with threads in Java a little over a week ago myself, so I apologize if what I'm suggestion is too basic or wrong.
My suggestion is, that you could create a static boolean variable that you could use for controlling your loop. Code could look something like this:
public static boolean isRunning;
public static void main(String[] args) {
ExecutorService executerService = Executors.newCachedThreadPool();
executerService.execute(new Runnable() {
#Override
public void run() {
isRunning=true;
while (isRunning){
System.out.println("hello world"); //Your loop here
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Whenever you set the isRunning boolean to false the loop will stop, and the Thread will finish after a little while.
As for observer-observable classes I don't know this and I'm not sure I understand your last question.
You can use a Timer to schedule a repeating task.
Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially
Something along the lines of this code should do the trick.
Timer timer = new Timer();
TimerTask task = new TimerTask(){
public void run() {
getPrice(); //your task
}
};
timer.schedule(task, 0, 5000); //first is delay, second is repeat period
...
// on button click, simple cancel the task
task.cancel()

what is the best approach to share a single thread between two independent continuous tasks in java

I have 2 continuous jobs called j1 and j2. These two jobs do not have any shared state.
I want to write a program that receives a threadpool of unknown size and share it on both jobs and if the threadpool size is one, the only thread be used for both jobs. in the following code j2 never starts.
I just want an alternative to this so the single thread be shared between both jobs (round robin for example)
#Test
public void testConcurrency(){
final Runnable j1 = new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("a");
}
}
};
final Runnable j2 = new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("b");
}
}
};
final ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(j1);
executorService.submit(j2);
executorService.shutdown();
}
I am trying to develop an architecture so that a specific number of threadpools be used in all modules for different tasks. This way I can control the number of threads created and I just need to inject them into modules. and I don't want to face deadlocks because of codes like this. so I was wondering if there is an alternative to code blocks like what I mentioned.
I have considered to force developers to use ScheduledExecutor instead of infinite loops, I just wanted to know if there is something missing that I haven't seen already.
You will have to do the switch between task yourself. For example, you could define an abstract task this way :
public abstract class AbstractContinuousTask implements Runnable {
private long maxDurationInMs = 100;
private ExecutorService execService;
public AbstractContinousTask(long maxDurationInMs, ExecutorService execService) {
this.maxDurationInMs = maxDurationInMs;
this.execService = execService;
}
#Override
public final void run() {
long start = System.currentTimeMillis();
while (!Thread.interrupted() && (System.currentTimeMillis() - start < maxDurationInMs)) {
runInternal();
}
execService.submit(this);
}
public abstract void runInternal();
}
which will call a runInternal method for a given duration (you could instead setup a number of call before returning, etc...).
and then, your task definitions become :
final ExecutorService executorService = Executors.newSingleThreadExecutor();
final Runnable j1 = new AbstractContinousTask(100, executorService) {
#Override
public void runInternal() {
System.out.println("a");
}
};
final Runnable j2 = new AbstractContinousTask(100, executorService) {
#Override
public void runInternal() {
System.out.println("b");
}
};
EDIT :
i've just seen you're last comment about developping a scheduling architecture. Have you looked in scheduling libraries, like Quartz, or Spring (with the #Scheduled annotation) ?
You could also use directly the java Timer api, this way :
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.println("a");
}
}, 0, 100);
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
System.out.println("b");
}
}, 0, 100);

How do I create an object that will start a thread that will run alongside my program?

I've been trying to work out how to create a Timer class that will count in milliseconds when you create a new object of that class.
public class Timer implements Runnable {
private long ms;
public Timer() {
this.ms = 0;
new Thread(this).run();
}
public Timer(long ms) {
this.ms = ms;
new Thread(this).run();
}
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
ms++;
Time.sleep(1);
}
}
public long getElapsed() {
return ms;
}
}
This is my Timer class, however, when I try to make an object of it:
Timer t = new Timer();
it gets stuck on the thread within the timer. I simply don't understand how I'm supposed to have a thread run continuously alongside my main program.
It should also be noted that I'm using this as an example as there are most likely better ways of creating a timer.
Thank you for your time.
I am not sure if you really want what you are trying to do here because this would waste a lot of CPU time for nothing.
Why don't you try something like this:
public class MyObject {
private long birthTime;
public MyObject() {
this.birthTime = System.nanoTime();
}
public long getElapsedMilliseconds() {
return (System.nanoTime() - this.birthTime) / (1000 * 1000);
}
}
Which can be used like this:
public static void main(String[] args) {
MyObject obj = new MyObject();
try {
Thread.sleep(1337);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("obj is " + obj.getElapsedMilliseconds() + "ms old");
}
And will return:
obj is 1337ms old
You only need to store the current time in milliseconds from that moment you create MyObject and then you can deduce the actual time your object is living/has lived by subtracting again the current time in milliseconds.
Instead of
new Thread(this).run()
use
new Thread(this).start()
But as Stefan Falk said, it would be better store the System.currentTimeMillis() and use it to calculate the "live time" of your object.

Java threads in Queue, once done with task, need to sleep

I have the following case to model
the program starts by querying the DB per received parameters and understanding the amount of tasks to be run.
Threads queue with some fixed max threads is defined to execute the tasks. Each task starts a flow that can have different configuration and can take different time. Once a tasks completes, each has a configurable sleep time.
Once a task sleeps, it cannot block a spot on the execution queue. The execution queue must continue with tasks that are ready to execute
I find it hard to code for some reason (mainly due to the last requirement)
Any help will be appreciated
Thanks
This is lengthy, but straight-forward code for illustration of scheduled resubmitter, which I haven't tested :)
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.*;
interface Repeatable {
boolean shouldBeRepeated();
/**
* #return how long to sleep
*/
long delayBeforeRepeat();
/**
* #return "initial" state of this task instance, so this state can be resubmitted for repeated execution
*/
BusinessTask reset();
}
/**
* Whatever suits your business logic
*/
interface BusinessTask extends Callable<Repeatable> {
}
class BusinessTaskCompletionData {
final BusinessTask businessTask;
/**
* Timestamp when this task should be resubmitted
*/
final long nextSubmitTime;
BusinessTaskCompletionData(BusinessTask businessTask, long nextSubmitTime) {
this.businessTask = businessTask;
this.nextSubmitTime = nextSubmitTime;
}
}
class TaskResusltsConsumer implements Runnable {
private final CompletionService<Repeatable> completionService;
private final Deque<BusinessTaskCompletionData> completedTasks;
TaskResusltsConsumer(ExecutorService executor, Deque<BusinessTaskCompletionData> completedTasks) {
this.completedTasks = completedTasks;
completionService = new ExecutorCompletionService<>(executor);
}
#Override
public void run() {
while (true) {
try {
Future<Repeatable> completedBusinessTask = completionService.take();
Repeatable repeatable = completedBusinessTask.get();
if (repeatable.shouldBeRepeated()) {
completedTasks.add(new BusinessTaskCompletionData(repeatable.reset(),
System.currentTimeMillis() + repeatable.delayBeforeRepeat()));
}
} catch (ExecutionException | InterruptedException ie) {
// handle somehow
}
}
}
}
class TasksSupplier implements Runnable {
private final Deque<BusinessTaskCompletionData> completedTasks;
private final ExecutorService executor;
TasksSupplier(Deque<BusinessTaskCompletionData> completedTasks, ExecutorService executor) {
this.completedTasks = completedTasks;
this.executor = executor;
}
#Override
public void run() {
while (true) {
BusinessTask t = getTaskSomehow();
executor.submit(getTaskSomehow());
}
}
private BusinessTask getTaskSomehow() {
// implement
return null;
}
}
/**
* Actual implementation of logic to obtain 'initial state' of task to repeat and repeat schedule
*/
class BusinessData implements Repeatable {
// whatever
}
public class SOTest {
public static void main(String[] args) {
final LinkedList<BusinessTaskCompletionData> tasksToRepeat = new LinkedList<>();
// workers pool
final ExecutorService workersPool = Executors.newFixedThreadPool(10);
// controllers pool: 1 thread for supplier, the other for results consumer
final ExecutorService controllersPool = Executors.newFixedThreadPool(2);
controllersPool.submit(new TasksSupplier(tasksToRepeat, workersPool));
controllersPool.submit(new TaskResusltsConsumer(workersPool, tasksToRepeat));
// resubmitter scheduled pool
ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
long now = System.currentTimeMillis();
Iterator<BusinessTaskCompletionData> it = tasksToRepeat.iterator();
while (it.hasNext()) {
BusinessTaskCompletionData data = it.next();
if (data.nextSubmitTime >= now) {
workersPool.submit(data.businessTask);
it.remove();
}
}
}
},
// initial delay of 1 sec
1000,
// periodic delay of 1 sec
1000,
TimeUnit.MILLISECONDS
);
}
}

Schedule infinite thread

I need to create a thread that runs infinitely as a stand alone process withing Spring MVC controller.
The thread will start when the controller is hit for the first time. I don't want to reschedule every time controller is hit.
#RequestMapping(method = RequestMethod.GET)
public String runTask() {
//I want this to be scheduled first time controller is hit but
//I don't want it to rechadule every time it is hit again
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// do stuff
}
}, 0, 5, TimeUnit.SECONDS);
return "Task was scheduled to run";
}
Java Thread every X seconds
Is there a better way to do this?
You can separate the logic for thread execution and controller initializing the executor something like below:
public class MapDecoratorQueue {
//inject it
MyXExecutor myXExecutor;
#RequestMapping(method = RequestMethod.GET)
public String runTask() {
myXExecutor.setRunning(true);
return "Task was scheduled to run";
}
}
//Inject this into MapDecoratorQueue in spring config
class MyXExecutor{
private final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
private volatile boolean isRunning = false;
public MyXExecutor(){
exec.scheduleAtFixedRate( new Runnable(){
#Override
public void run() {
if(isRunning){
//do stuff
}
}
}, 0, 5, TimeUnit.SECONDS);
}
public void setRunning(boolean running) {
isRunning = running;
}
}
Put your run logic under check of isRunning value. If you don't want to start the executor at all till you get first hit you can use the same approach and you can call a method from controller which will init the Executor if its not initialized.
Hope this helps.
just add this to controller
#PostConstruct
public void init(){
//call executor here
}

Categories

Resources