I am writing a code in Java, that has three main methods which are called in succession. Today, my prof, told me to improve the code by setting a frequency to code which means it that there should be a specific time allocated for each method. If it is done before that time, it should wait for that much time and then call should go to next method.
For example: If the first method has time of 3 seconds, for three seconds it should wait there even if it is done, then move to next method sense.
I am already using a timer in my code to slow down the movement as it is a GUI. I was planning to use another timer, but I feel it will only slow it down. How can I fix the period for that method for a specific time say 3 seconds.
Please let me know if you have any ideas.
If you cannot sleep on your own thread, run the task on another thread. A single executor thread will do nicely, to which you can submit tasks to be executed. Sleeping in the executor thread should not impact the GUI thread.
private Executor executor = Executors.newFixedThreadPool(1);
public void method1() {
System.out.println("Method 1 called");
}
public void method2() {
System.out.println("Method 2 called");
}
public void method3() {
System.out.print("Method 3 called");
}
public void start() {
executor.execute(new Runnable() {
private final long WAIT_TIME = 3000; // ms
#Override
public void run() {
long startTime = System.currentTimeMillis();
method1();
sleep(startTime);
startTime = System.currentTimeMillis();
method2();
sleep(startTime);
startTime = System.currentTimeMillis();
method3();
sleep(startTime);
}
private void sleep(long startTime) {
long timeTaken = System.currentTimeMillis() - startTime;
long timeLeft = WAIT_TIME - timeTaken;
if(timeLeft < 0) return;
try {
Thread.sleep(timeLeft);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
Related
I have a method, which writes to the database. The requirement is to make sure that this method does not execute after a certain time elapses. If it returns before that, then nothing should be done.
The one basic approach that I can think of is doing something like this.
public class LimitedRuntime {
public static void writeToDb(){
// writes to the database
}
public static void main(String[] args) {
long totalExecutionTime = 8000L;
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < totalExecutionTime )
{
writeToDb();
}
}
}
One problem with this approach is that even if the method returns before the max total execution time, even then the program halts so as to wait for the time to elapse.
How can I do this better (or maybe more correctly) ? And if we use Thread, how can we find out which Thread executes that method ?
You can do this by sending your job to an executor:
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(new Runnable() {
#Override
public void run() {
writeToDb(); // <-- your job
}
});
executor.shutdown(); // <-- reject all further submissions
try {
future.get(8, TimeUnit.SECONDS); // <-- wait 8 seconds to finish
} catch (InterruptedException e) { // <-- possible error cases
System.out.println("job was interrupted");
} catch (ExecutionException e) {
System.out.println("caught exception: " + e.getCause());
} catch (TimeoutException e) {
future.cancel(true); // <-- interrupt the job
System.out.println("timeout");
}
// wait all unfinished tasks for 2 sec
if(!executor.awaitTermination(2, TimeUnit.SECONDS)){
// force them to quit by interrupting
executor.shutdownNow();
}
}
There is also an AspectJ solution for that with jcabi-aspects library:
#Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String writeToDb() {
// writeToDb
}
There is an article explaining it further: Limit Java Method Execution Time
I have a while function. When it is true I want to proceed it only every 1 second. I can't use Thread.sleep(), because I am making Minecraft plugin and it will stop all processes on the server. Is there another way how to do it?
Thanks for your reply.
What you are looking for is the Bukkit Scheduler. It is integrated into the default plugin API and can be used to solve your task as following:
int taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
#Override
public void run() {
// do stuff
}
}, delay, repeat);
Set the delay to 0 and the repeat to 20 (20 Ticks are 1 second).
Stop it by using:
Bukkit.getScheduler().cancelTask(taskID);
you can create a java.util.TimerTask
which can schedule your task after a specified time delay .
more details here : https://www.geeksforgeeks.org/java-util-timertask-class-java/
If you use Thread.sleep() in the main Thread you will block the main thread and for avoid this you need to create a separate thread pass to then the values you will need for process whatever you want in your thread, some snippet code for clarification:
public static boolean ENABLE_THREAD = true;
public static void main(String args[]){
InnerThread minecraftThread = (new ThreadStack()).new InnerThread();
minecraftThread.run();
}
public class InnerThread implements Runnable{
#Override
public void run() {
int counter=0;
while(ENABLE_THREAD){
try {
//YOUR CODE
System.out.println(counter);
Thread.sleep(1000);
counter++;
if(counter>10){
ENABLE_THREAD = false;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You can use System.currentTimeMillis():
public static void main(String[] args) {
//The while(true) is to keep the next while loop running, otherwise, in
//this example, the condition System.currentTimeMillis()-past>=1000
//won't be true
//It can be changed according to the needs
long past = System.currentTimeMillis();
while(true)
while(System.currentTimeMillis()-past>=1000)
{
/*
*DO what you need to do
*/
past = System.currentTimeMillis();
}
}
This is the simplest solution I can think of. Please check if it works for you.
long start = new Date().getTime();
while(new Date().getTime() - start < 1000L)
{
//Do Something every 1sec
//you need to update the start value everytime
start = new Date().getTime();
}
I want to run a task at every particular interval of time regardless of completion of previous thread. And I've used ScheduledExecutorService with the schedule time at every one second. But the problem is, in my Runnable, If I make thread to sleep for 5 seconds, My ScheduledExecuterService also getting executed in every 5 seconds while it supposed to run each thread at 1 second.
It seems like it ScheduledExecuterService is waiting for previous thread to completion. But I want, The task to be triggered at every 1 second no matter what if job inside the task waits for longer time.
Here's is my code.
public class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And here's my ScheduledExecutorService Code.
public class JavaScheduledExecutorServiceExample {
public static void main(String[] args) {
ScheduledExecutorService execService = Executors.newScheduledThreadPool(5);
execService.scheduleAtFixedRate(new MyTask(), 0, 1000, TimeUnit.MILLISECONDS);
}
}
Correct me If I'm doing something wrong. And If I'm wrong, is there any alternative to achieve the same? Providing Any best practices could be more helpful :)
"If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute." The behavior you are seeing is consistent with the javadocs
I believe this will perform the way you specified:
public class JavaScheduledExecutorServiceExample {
private static ScheduledExecutorService execService = null;
private static int timesAsleep = 0;
public static class MyTask implements Runnable {
public void run() {
System.out.println("hi there at: "+ new java.util.Date());
// schedule again
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
try {
int i = timesAsleep;
timesAsleep++;
System.out.println("asleep " + i + "----------------------");
Thread.sleep(5000);
System.out.println("awoke " + i + "----------------------");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
execService = Executors.newScheduledThreadPool(5);
execService.schedule(new MyTask(), 1000, TimeUnit.MILLISECONDS);
}
}
Notice the use schedule() instead of scheduleAtFixedRate() on the ScheduledExecutorService instance. It also schedules the next task as soon as it starts the new task.
I have a method, which writes to the database. The requirement is to make sure that this method does not execute after a certain time elapses. If it returns before that, then nothing should be done.
The one basic approach that I can think of is doing something like this.
public class LimitedRuntime {
public static void writeToDb(){
// writes to the database
}
public static void main(String[] args) {
long totalExecutionTime = 8000L;
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < totalExecutionTime )
{
writeToDb();
}
}
}
One problem with this approach is that even if the method returns before the max total execution time, even then the program halts so as to wait for the time to elapse.
How can I do this better (or maybe more correctly) ? And if we use Thread, how can we find out which Thread executes that method ?
You can do this by sending your job to an executor:
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(new Runnable() {
#Override
public void run() {
writeToDb(); // <-- your job
}
});
executor.shutdown(); // <-- reject all further submissions
try {
future.get(8, TimeUnit.SECONDS); // <-- wait 8 seconds to finish
} catch (InterruptedException e) { // <-- possible error cases
System.out.println("job was interrupted");
} catch (ExecutionException e) {
System.out.println("caught exception: " + e.getCause());
} catch (TimeoutException e) {
future.cancel(true); // <-- interrupt the job
System.out.println("timeout");
}
// wait all unfinished tasks for 2 sec
if(!executor.awaitTermination(2, TimeUnit.SECONDS)){
// force them to quit by interrupting
executor.shutdownNow();
}
}
There is also an AspectJ solution for that with jcabi-aspects library:
#Timeable(limit = 5, unit = TimeUnit.SECONDS)
public String writeToDb() {
// writeToDb
}
There is an article explaining it further: Limit Java Method Execution Time
I am trying to make an ExecutorService implementation that can be provided with a timeout or interrupt for each thread.
In my below example, suppose I am spawning 2 threads (in actual scenario, this number will be high), then I need to make sure each thread should be running for 10 minutes.
That means, Thread1 will run for 10 minutes and Thread2 will run for 10 minutes as well. If 10 minutes is over then I need to interrup the thread or timeout.
Below is the code I have so far and I am not able to understand how should I add this interrupt or timeout functionality here in such a clean way so that if I am making this no of threads parameter configurable in my code then it should work properly there as well.
public static void main(String[] args) {
final int noOfThreads = 2;
final long exp_time_millis = 600000; //10 minutes
//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);
for (int i = 0, i< noOfThreads; i++) {
service.submit(new ThreadTask());
}
}
class ThreadTask implements Runnable {
#Override
public void run() {
while(true) {
System.out.println("Thread running...");
try {
/* make a select sql to the database
* and measure how much time it is taking in
* returning the response
*/
} catch (InterruptedException e) {
}
}
}
}
Any suggestions will be of great help.
I have already seen few articles on the SO but I was not able to find anything which matches my scenario and I can implement that easily.
Updated Code:-
I am trying the below code but it gives me error on the catch block in the run method. Not sure if I am doing anything wrong. Can anyone help me?
public class ThreadTimeout {
public static void main(String[] args) {
final int noOfThreads = 2;
//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);
ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(noOfThreads);
for (int i = 0; i< noOfThreads; i++) {
final Future future = service.submit(new ThreadTask());
scheduleService.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, 10, TimeUnit.MINUTES);
}
}
}
class ThreadTask implements Runnable {
#Override
public void run() {
//make a database connection
while (true) {
System.out.println("Thread running...");
try {
/*
* make a select sql to the database and measure
* how much time it is taking in returning the
* response
*/
} catch (InterruptedException e) {
}
}
}
}
I would recommend using a second ScheduledExecutorService. You can submit the Future returned from your original submissions to the ScheduledExecutorService to cancel.
ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(n);
for (int i = 0, i< noOfThreads; i++) {
final Future future = service.submit(new ThreadTask());
scheduleService.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, 10, TimeUnits.MINUTES);
}
Now the ThreadTask needs to respond to interruption or else this will not help.
What I would recommend is to use the ExecutorService.awaitTermination(...); method and then the ExecutorService.shutdownNow() method.
For example:
for (int i = 0; i < noOfThreads; i++) {
service.submit(new ThreadTask());
}
// we always need to shutdown the service _after_ we've submitted all jobs
service.shutdown();
// now we wait for those tasks to finish for 10 minutes
if (!service.awaitTermination(10, TimeUnit.MINUTES)) {
// if we timed out waiting for the tasks to finish, forcefully interrupt them
service.shutdownNow();
}
Note that this will interrupt the threads but that will only cause certain methods such as Thread.sleep(), Object.wait(), and some others to throw InterruptedException. It also sets the interrupt bit on the thread which can be tested with Thread.currentThread().isInterrupted(). It will not "kill" the thread like you would a unix process.