Restart Runnable Variables Android - java

I want to do something that i am not sure can be done, and so far i haven't found any good answers to my question.
Here is my situation:
- I have implemented Timer as a Handler that has Runnable that is calling itself every 1s.
- I need now to implement a method like Timer.restart() that can restart my Runnable's params.
Here is my code so you can see it, and better understand what i have tried to achieve
private Runnable rStartCPRTick = new Runnable() {
public int seconds = 0;
public int minutes = 0;
public int hours = 0;
#Override
public void run() {
if(++seconds%60 == 0) //increases the time by one second
if(++minutes%60 == 0)
hours++;
mActivity.updateCPRTime(formatHHMMSS(hours,minutes,seconds));
mStartCodeHandler.postDelayed(this,1000); // tick again in 1s
}
public void restartCPRTick(){
seconds = 0;
minutes = 0;
hours = 0;
}
};
My runnable, i want to be able to call resetCPRTick() from outside Runnable and then call run that starts from the beggining.
Is such thing possible?
Thanks!!

Your runnable is a class. You can add any methods to it you want. Just keep a reference to it around and call a method that does it (to do this you probably want to make it a inner class rather than an annonymous class).

Related

Calling a function every 2 minutes

I'm working on a plugin for a Minecraft server which automatically breaks melons for melon farms. It loops through all the blocks in all players' current chunks, and breaks the blocks that are melons. At first, I attempted to continuously call this function with a while loop in the onEnable method, however that caused the server to time/lag out. Without the while loop (only calling the function once from the onEnable), the plugin worked fine. Every time I reloaded the server, the function would run and all melons would be broken; so I decided to make a timer that would call the function every two minutes. For some reason, the server still times out, even with the timer, which I don't understand
Here's my code:
package me.spigot.itiurray.main;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public class Main extends JavaPlugin {
private long goTime = 0;
#Override
public void onEnable() {
getLogger().info("MelonDrop has been enabled.");
startBreakWithInterval();
}
private void breakMelons() {
for (Player player : Bukkit.getOnlinePlayers()) {
Chunk chunk = player.getLocation().getChunk();
int x = chunk.getX() << 4;
int z = chunk.getZ() << 4;
for (int xx = x; xx < x + 16; xx++) {
for (int zz = z; zz < z + 16; zz++) {
for (int yy = 0; yy < 256; yy++) {
Block block = chunk.getBlock(xx, yy, zz);
if (block.getType().equals(Material.MELON_BLOCK))
block.breakNaturally();
goTime = System.currentTimeMillis() + 120000;
}
}
}
}
}
private void startBreakWithInterval() {
boolean running = true;
while (running == true) {
if (System.currentTimeMillis() >= getGoTime())
breakMelons();
}
}
private long getGoTime() {
return goTime;
}
}
Edit: Here's what it currently looks like...
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
#Override
public void onEnable() {
getLogger().info("MelonDrop has been enabled.");
scheduledExecutorService.scheduleWithFixedDelay(() -> breakMelons(),
2, 2, TimeUnit.MINUTES);
}
Your code is stuck inside the while(running == true)
I suggest you to use a ScheduledExecutorService
For your time logic you should do the following
if(System.currentTimeMillis() - getGoTime() >= 120000)
{
breakMelons();
}
Then inside your break melons function just call it at the very end of your method outside your for loop and do the following
goTime = System.currentTimeMillis();
The goTime variable should really just be the time at which you last completed breaking all the melons. Then when you check that time against the current system time you check if the time difference between the current time and the last time you executed the melon function is greater than 120000ms.
A much clearer solution would look like this:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
breakMelons()
}
}, 2, 2, TimeUnit.MINUTES);
This will be calling your method each 2 minutes. Also if you support java 8 then you could use the following syntax:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.scheduleWithFixedDelay(() -> breakMelons(), 2, 2, TimeUnit.MINUTES);
The correct solution for this is to use a BukkitRunnable. You can see more examples at bukkit's documentation
JavaPlugin plugin; //Your plugin instance
Long timeInSeconds = 10;
Long timeInTicks = 20 * timeInSeconds;
new BukkitRunnable() {
#Override
public void run() {
//The code inside will be executed in {timeInTicks} ticks.
//After that, it'll be re-executed every {timeInTicks} ticks;
//Task can also cancel itself from running, if you want to.
if (boolean) {
this.cancel();
}
}
}.runTaskTimer(plugin, timeInTicks, timeInTicks); //Your plugin instance,
//the time to wait until first execution,
//the time inbetween executions.
Most other answers use BukkitRunnables and other native Java libraries. The best way to do this would be using a schedule task using a Runnable, not a BukkitRunnable.
Bukkit.getScheduler().scheduleSyncRepeatingTask(myPlugin, new Runnable() {
#Override
public void run() {
breakMelons();
}
}, 0, 2400);
The code below uses the recommended way of running a simple task repeatedly.
The reason you do not want to use BukkitRunnables the way that is recommended in another answer is because it creates a variable that is called and then left orphaned. This code uses an inline anonymous inner class in order to keep everything neat and tidy, while also giving you the same effect.
The only time you want to use a BukkitRunnable rather than just a normal Runnable, is when you have an intention of stopping the task in the future.

separating threads but still keeping a common variable in java

My project group is creating a traffic simulation and we are not sure how to split threads properly. We have the update method below that has 1 variable delta. Now we want to split both for loops (updating vehicles in the first and the second updates all intersections etc). How does one split these into 2 threads yet still being able to give them the same value for delta? Is this even possible? We can only get it to work putting the entire method into 1 thread, but then we can not split them.
EDIT: the delta is a constantly changing variable (time passed) this is the reason it's hard to get both to use the same delta.
public void update(double delta){
for (int i = 0; i < this.vehicles.size(); i++) {
this.vehicles.get(i).update(delta);
}
for (int i = 0; i < this.updateables.size(); i++) {
this.updateables.get(i).update(delta);
}
this.simulationTime += delta;
}
If this.vehicles is a List, or something along those lines, create a parallel stream.
this.vehicles.stream().parallel().forEach(v->v.update(delta));
Then they should be run in parallel.
An alternative way, if you want more control over the process, use an executor service.
ExecutorService service = Executors.newFixedThreadPool(4);
Then submit each task.
List<Future<?>> futures = this.vehicles.map(
v->service.submit(
()->v.update(delta)
)
).collect(Collectors.toList());
Then to make sure all of the tasks complete.
futures.forEach(future->{
try{
future.get();
}catch(Exception e){
//two types of exceptions they both should be handled appropriately.
}
});
If I understand you right, delta may vary.
You can create two seperate Threads, for example here the one for the vehicles:
public class VehiclesUpdater extends Thread {
double delta;
List<Vehicle> vehicles;
public VehiclesUpdater(double delta, List<Vehicle> vehicles) {
this.delta = delta;
this.vehicles = vehicles;
}
#Override
public void run() {
for(int i=0;i<vehicles.size();i++) {
vehicles.get(i).update(delta);
}
}
}
Then, instead of calling the loop, just do as follows:
public void update(double delta) {
Thread t = new VehiclesUpdater(delta, vehicles);
t.start();
//the same here for the Updateables
}
EDIT:
Because you are concerning time issues, you may try an Observer/Observable-approach.
Let your Vehicle-class and your Updateable-class extend the Observer class: Observer
In the class which computes the delta-value(s), implement the Observable interface. If it changes, call the setChanged() method and after that the notifyObservers() method and give delta or an Double-Wrapper as param to it:
Double wrapper = new Double(delta);
setChanged();
notifyObservers(wrapper);
In your vehicle-class, you have to override the update-method of Observer:
//
#Override
public void update(Observable o, Object arg) {
this.updateDelta((Double)arg);
}
I just called your original update-method updateDelta for clarification - it should be possible to use method-overloading here as long as your update-method will use another param (double) and has the same method-head with public void update(...).

Exact same code (with multithreading) doesn't work on 2 different computers

I'm working at the moment on a simple Chess A.I. (calculate possible future turns, rate them, chosse the best one, + some tricks so you don't have to calculate every single turn). The code is written in Java and I'm using Netbeans. To make the calculations faster, I use multithreading. The code works roughly like this:
Main function makes first some calculations and then starts 8 threads.
the threads execute the main-calculations
when they finish, they set a boolean value in a boolean array (finished[]) true. This array is in the "main Class" (if you call it like this), where also the main function is.
during all this time the main function is waiting and checking constantly if every value of the finished[] - array is true. If that is the case, it continues it's work.
Now I have a strange problem. The code works perfectly on my PC, but when I run the EXACT same code on my laptop, the main function won't continue its work, after all values of the finished[]-array are true. I already made some changes in the code, so I can try it with different numbers of threads, but the result is always the same.
I have totally no idea what's going on here and would really appreciate it, if someone of you had any answers and/or suggestions!
If you need any more Information just ask, I'll try my best. :)
(Sorry for possible grammar mistakes, english isn't my native language, but I'm trying my best. ;))
So I was asked to show some Code I used in the program:
(Perhaps first a warning, yes I am still a big Noob in Java and this is my first time I work with threads so don't be shocked if you see terrible mistakes I possibly made. xD)
The main Class looks something like this:
public class Chess_ai_20 {
static boolean finished[] = new boolean[8];
Distributor[] Distributors = new Distributor[8];
...
public static void main(String[] args) {
boolean testing=false;
...
//some calculations and other stuff
...
Distributors[0] = new Distributor(...., "0"); //the String "0" will be the thread name.
Distributors[1] = new ...
...
Distributors[7] = new Distributor(...., "7");
for (int i = 0; i < 8; i++) {
Distributoren[i].start();
}
testing=false;
while(testing==false){
if(finished[0]==true && finished[1]==true && ... && finished[7]==true){
testing=true; //That's the point where I get stuck I suppose
}
}
System.out.println("I made it!");
}
public static void setFinished(int i) {
finished[i] = true;
System.out.println("finished [" + i + "] = " + finished[i]);
System.out.println(Arrays.toString(finished)); //To check how many values already are true
}
}
Then we got of course the class "Distributor"
public class Distributor extends Thread {
Thread t;
String threadname;
boolean running=false;
...
Distributor(......, String s) {
threadname=s;
...
...
}
#Override
public void start() {
running=true;
if (t == null) {
t = new Thread(this,threadname);
t.start();
}
}
#Override
public void run() {
if(running){
...
//Do the main calculations etc.
...
//All the Calculations habe been done at this point
Chess_ai_20.setFinished(Character.getNumericValue(threadname.charAt(0))); //Set the value of finished[] true in the main class
running=false;
}
}
}
As others have mentioned, using a Future would be much simpler and easy to understand. Below is a snippet demonstrating how you could rewrite your code. Check out the code in action.
First, you write a Callable to define the task that you want to do.
public class MyCallable implements Callable<Boolean> {
#Override
public Boolean call() {
// Do some job and return the result.
return Boolean.TRUE;
}
}
And then, you submit this task to an Executor. There are a lot of Executors in JDK. You want to go through the Concurrency Tutorial first.
ExecutorService executor = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
List<Callable<Boolean>> callables = new ArrayList<>();
for (int counter = 0; counter < 8; counter++) {
callables.add(new MyCallable());
}
List<Future<Boolean>> futures = executor.invokeAll(callables);
for (Future<Boolean> future : futures) {
System.out.println(future.get()); // You'd want to store this into an array or wherever you see fit.
}
executor.shutdown();
Remember that the futures returned by the executor are in the same order as the Callables you submitted (or added) to the Collection (in this case, an ArrayList). So you don't need to worry about returning the index, an ID or even the name of the Thread (if you assigned one) to map the corresponding result.

How to create a Java function which Once called, cannot be called Again unless there is some DELAY?

I'm trying to make a function which can ONLY be called again after there is some amount of time delay between the two calls, (Say 5 seconds).
I require this functionality for an android app I'm creating.
Since it is possible that the user would be calling that function too frequently within a few seconds, it would destroy his experience. Hence, I'm desperately looking for an answer on this.
public void doSomethin(){
//code here which makes sure that this function has not been called twice within the specified delay of 5 seconds
//Some code here
}
Any help would be awesome!
Adit
You could hold the time in milliseconds and check if the current time is greater than or equal to the previous time + 5 seconds. If it is, execute the method and replace the previous time with the current time.
See System.currentTimeMillis()
public class FiveSeconds {
private static Scanner scanner = new Scanner(System.in);
private static long lastTime = 0;
public static void main(String[] args) {
String input = scanner.nextLine();
while(!input.equalsIgnoreCase("quit")){
if(isValidAction()){
System.out.println(input);
lastTime = System.currentTimeMillis();
} else {
System.out.println("You are not allowed to do this yet");
}
input = scanner.nextLine();
}
}
private static boolean isValidAction(){
return(System.currentTimeMillis() > (lastTime + 5000));
}
}
If the code runs on your main thread, Thread.sleep(5000) is not an option. The easiest way to go then would be:
private long previous = 0;
public void doSomething() {
long now = Calendar.getInstance().getTimeInMillis();
if (now - previous < 5000)
return;
previous = now;
// do something
}
use a static field, which saves the datetime of last execution and before executing check the current datetime against this timestamp.
I won't write code for you but if you think a bit about this it's not that hard. You want to make sure it's not called before 5 seconds has passed since last function call. Let's split this into parts.
1) Get current time
2) Compare to stored time that keeps it value between calls.
3) If less than 5 seconds has passed don't do anything
4) Otherwise store the new value and do stuff.
I never did coding in Android. But if Android has threads (which is most likely, it does). Then within this function sleep the thread for 5 seconds, it means even though it is called, it won't be executed further until 5 seconds are passed
public void doSomething()
{
Thread.sleep(5000); // Please find the corresponding Android method
}
make doSomethin() as a private method.
Expose another function say exposedDoSomething().
public void exposeDoSomething(){
// Add to a queue
}
In a separate thread read the queue in every 5 mins and call doSomethin()
Maybe a TimerTask will help you, more details here:
TimerTask|Android Developers
Example:
private TimerTask tiemrTast= new TimerTask() {
#Override
public void run() {
}
};
And then use this method: public void scheduleAtFixedRate (TimerTask task, long delay, long period)
One problem is that you'll have to have a session level timer for each and every user. This could be a fair amount of overhead depending on how many simultaneous users you have.
It's easy for one user: start a timer on request. It's distinguishing between users that's the problem. Your service is now stateful, which is usually a bad thing. You're giving away idempotence.
You could also maintain state in a database. Don't worry about calls; check persistent operations to make sure they don't happen too frequently.
It's not clear to me whether you mean to exclude all users for five seconds once the method is called by anyone, or if every user is prevented from calling the method again for five seconds once it's called the first time.
This sounds like a throughput killer. I'd reconsider this design.
you can use hander.postDalayed method to call method to run after specific delay
you can use your method something like this
int delay=5000;
int k;
int iDelayTimeInMiliSeconds=2000;
for( k=0;k<arrBatch.size();k++)
{
delay=delay+iDelayTimeInMiliSeconds;
callAllDocumentList(arrBatch.get(k),k,delay);
}
public void callAllDocumentList(final String strInvoiceId,final int count,int delay)
{
mHandler.postDelayed(new Runnable()
{
#Override
public void run()
{
// call your function here that you want to call after specific delay
//getOrderDetails(strInvoiceId,count,true);
}
}, delay);
}

android thread and handler best practices

I have the following class. The purpose of the class is to allow me to simulate a teletype/typewriter by displaying about ten characters a second.
The point of the CharacterLoopThread class is to look at the outputBuffer, and if there are any characters in it, invoke a runnable on the UI thread that pulls off the first character and plops it into the textView. The thread then sleeps for about 100ms. (There are some shenanigans here... while the teletype was amazing when I used it in 1979, it's a little slow for my tastes now. So every 10 characters, I reduce the delay slightly. When there are no more characters to display, I reset the delay to 100ms...)
I edited off the bottom of the class since it was not germane to my question.
What I have here seems to work well. However, does it work because of me or in spite of me? What are your preferred ways of writing Threads and Handlers?
public class MyActivity extends Activity {
private TextView textView;
private ScrollView scrollView;
private StringBuilder outputBuffer;
private Handler handler;
private CharacterLooperThread characterLooperThread;
(snip)
private class CharacterLooperThread extends Thread {
private boolean allowRun;
private Runnable run;
int effectiveCharacterDelay;
int characterCount;
public CharacterLooperThread() {
allowRun = true;
run = new Runnable() {
public void run() {
/**
* Don't do anything if the string has been consumed. This is necessary since when the delay
* is very small it is possible for a runnable to be queued before the previous runnable has
* consumed the final character from the outputBuffer. The 2nd runnable will cause an
* exception on the substring() below.
*/
if (outputBuffer.length() == 0) return;
try {
textView.append(outputBuffer.substring(0, 1));
scrollToBottom();
outputBuffer.deleteCharAt(0);
} catch (Exception e) {
toast(getMsg(e));
}
}
};
}
public void run() {
resetDelay();
while (allowRun) {
/**
* This if() performs 2 functions:
* 1. It prevents us from queuing useless runnables in the handler. Why use the resources if
* there's nothing to display?
* 2. It allows us to reset the delay values. If the outputBuffer is depleted we can reset the
* delay to the starting value.
*/
if (outputBuffer.length() > 0) {
handler.post(run);
reduceDelay();
} else {
resetDelay();
}
try {
Thread.sleep(effectiveCharacterDelay);
} catch (InterruptedException e) {
toast("sleep() failed with " + e.getMessage());
}
}
/**
* Make sure there's no runnable on the queue when the thread exits.
*/
handler.removeCallbacks(run);
}
public void exit() {
allowRun = false;
}
One idea is to use Handler.postDelayed to schedule the individual "keystrokes". You can either do this all at once, or have each keystroke Runnable schedule the next as it finishes; if processing gets behind schedule, the former approach will catch up as quickly as possible, while the latter will essentially push everything back to keep the same inter-keystroke delay.
It worries me to see one thread altering the StringBuilder while another reads it. (The StringBuilder class was a non-thread-safe successor to StringBuffer, which was written back in the day when folks thought making individual classes thread-safe was good design). If it doesn't occasionally do something unexpected, you're lucky, though not much can go wrong here. Using postDelayed, however, you might get rid of the background thread altogether.
As long as you are making anonymous Runnable classes, note that you can feed them arguments (as long you declare variable final). So I would tend to post one character at a time to each Runnable, like this:
long delay = 0;
for (int j = 0; j < outputBuffer.length(); ++j) {
final CharSequence s = outputBuffer.subSequence(j, j + 1);
handler.postDelayed(new Runnable() {
#Override public void run() {
textView.append(s);
scrollToBottom();
}
}, delay);
delay += 100; // or whatever
}

Categories

Resources