I have a thread that runs while a condition is false. For each second it is false, then it will add 1 second to the time, then return that time. My problem is that at the end of the code, it returns no output, that is, no integer variable is returned to output.
Note: For this program, assume that the user correctly guesses the number, and win is true.
Edit: Code execute() has been added to the while win = false
Thread thread = new Thread() {
public int run(boolean win){
int time = 0;
while(win == false) {
try {
time++;
Thread.sleep(1000);
}
catch(Exception e) {
}
}
return time;
}
};
public void execute() {
thread.start();
}
This thread continues to increase while win is false, then returns the value of time when win is true.
public void userGuessNumber() {
boolean win = false
[...] // Options Menu Code - timer should not increment for this section
while(win == false) {
execute();
if(guess == number) {
win = true;
}
[...] // Do some code
}
}
Win is true when user guesses a number correctly. That is when the thread should stop incrementing. Then below is when the method outputs the time:
public void outputInfo() {
System.out.print("The time it had taken to guess the number: ");
execute();
}
Edited Code: I have added execute() in the while loop; my logic is that I want the thread to begin counting only when the user starts guessing a number. The execute() statement in the outputInfo method, I intend to print the number generated from time when the thread was running, but I believe this could be semantically incorrect.
execute is a method that runs the thread code, but for some reason the output it empty, and returns nothing.
Instead, I want it to return the number of the time that has elapsed before win reached true.
This really isn't the proper use of a thread. Multithreading should be used for event handling or having long background processes such as a download.
You can easily just track the time by using System.currentTimeMillis(), assigning it to a variable and you'll be able to get the difference of time in milliseconds. If you want it in seconds, just divide by 1000.
Here's a snippet:
public void userGuessNumber() {
boolean win = false
[...] // Options Menu Code - timer should not increment for this section
long guessNumberStarted = System.currentTimeMillis();
int timeElapsed = 0;
while (!win) {
if (guess == number) {
win = true;
timeElapsed = (int)(System.currentTimeMillis() - guessNumberStarted) / 1000;
}
}
[...] // Do some code
}
Not only is the code shortened, you don't have any unneeded code running in the background, and you can calculate the amount of time that passed with more accuracy, given that you make the variable a double or a long.
Related
How to be limit number of times call and runs method OnScrolled() in RecyclerView ?? Because there are a number of conditions in it, very much executing this code,Cause slowdown the application.
condition :
if (dy < 0 && mLinearLayoutManager.findFirstCompletelyVisibleItemPosition() >= 10 && !mStateScrollTop) {
YoYo.with(Techniques.SlideInUp)
.duration(150)
.playOn(iv_go_to_top);
mStateScrollTop = true;
} else if (dy > 0 && mStateScrollTop) {
YoYo.with(Techniques.SlideOutDown)
.duration(150)
.playOn(iv_go_to_top);
mStateScrollTop = false;
}
I would do something like this:
onScrolled() {
synchronized(this) {
if(!ready)
return;
else
ready = false;
}
// your current onScroll body
}
And then you would launch a thread setting a ready variable to true in regular intervals. Something like this:
private void launchOnScrollThread() {
new Thread() {
#Override
public void run() {
// endless loop - maybe you would like to put some condition to end the loop
for(;;) {
ready = true;
Thread.sleep(100); // wait here for 100 milliseconds
}
}
}.start();
}
This would ensure that your current code in onScroll will be executed at most every 100 milliseconds, which should speed it up. Sorry that it's kind of a pseudocode, hope it makes sense to you and will be helpful.
I want to check if an int value is higher than 20 for a certain amount of 15 minutes, if that int value stays higher than 20 in those 15 minutes, code will executed
I didn't understand the difference between a Handler and a Runnable, how to use them, What do they do...
My question is:
How can I run an if statement for a certain time using a Runnable/Handler
This is the if statement which I want to be checked for 15 mins,
if(Speed > 20){
// Code that will run after 15 mins IF the speed is higher than 20 for all that time
}
add this, this timer will execute after 1 sec you can add your time you want and put your if statement inside run function
private Timer myTimer;
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
Try using below code. It uses a while loop which will keep of looping for-ever until two condition are met
1) i becomes greater than 20
2) flag is set to false
For each iteration, it will sleep for 1 minute
public static void main(String[] args) {
int i = 0;
boolean flag = true;
try {
while (i < 20 && flag) {
TimeUnit.MINUTES.sleep(1);
// Expecting some logic to increment the value of i
// Or change the flag value of this to exit the while loop
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
I have a simple game where a player shoots some bullets. However, I want to make it so that the player can only shoot a bullet every x seconds. How would I do this?
I have tried to do it by taking the average time between bullets and saying that if average time is less than one second don't let the space bar (the control for shooting) work. However, I don't know how to make the space bar not work, AND that would mean a player could just not shoot for a wile and then shoot a lot of bullets at once.
The method for shooting looks something like this:
public void keyPressed(KeyEvent e) {
if (!keysDown.contains(e.getKeyCode()))
keysDown.add(new Integer(e.getKeyCode()));
This adds the integer of the key value to an array, which is then read here:
if (keysDown.contains(KeyEvent.VK_SPACE)) {
b = new Bullets(x);
bullCount.add(b);
System.out.println(bullCount.get(0).getY());
System.out.println ("There are " + bullCount.size() + "bullets alive.");
//elapsed = System.nanoTime() - start;
//if ((elapsed / bulletCount) < 1000000000) {
//this is where I would say 'no more bullets shot until
//average time in nanoseconds is more than 1 second!' but I don't know how
//}
Make a global variable ie: long lastShot.
When user shot, check if (System.currentTimeMilis()-lastShot>5000) before you allow him to shoot.
If it is ok to shoot, store the lastShot = System.currentTimeMilis(); and do the real shot. If not, don't allow him to shoot.
Here is an example in pseudo-code:
class SomeClass {
private long lastShot;
public void userPressedShot() {
if (System.currentTimeMillis()-lastShot>5000) {
lastShot = System.currentTimeMillis();
doTheRealShot();
}
// Ignored till 5000 miliseconds from last shot
}
}
One overkill option is to use the Guava's RateLimiter
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
while(true) {
rateLimiter.acquire();
shootSomething();
}
For this solution I assume that you use a Player Object.
It's very simple:
1.: add the field lastShot of the type long with the value 0 to your class.
2.: Whenever the player shoots, set lastShot to System.currentTimeMillis()
3.: Now, before you let him shoot, check if System.currentTimeMillis()-lastShot is smaller than your bullet delay in seconds.
This would be a MWE which has to be inserted in your player class:
Just call the Method player.shoot() to let him shoot - or not, if it's not possible.
private long lastShot = 0;
//return value is for you to check if the shot happened
public boolean shoot(){
//Did the last shot happen less than 1 second (1000 milliseconds) ago
if(System.currentTimeMillis()-lastShot <= 1000){
//If yes: return false, the shot can not happen
return false;
}else{
lastShot = System.currentTimeMillis();
//If no: insert your shooting code here to be executed
//return true, the shot happened
return true;
}
}
Try using a timer that resets every second the bullets count :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
bullCount.clear();
}
}, 0, 1000); // 0 is the delay in milliseconds before it starts and 1000 is the time in milliseconds between successive task executions
Then when a player wants to shoot you just have to look at bullCount's size
I am working on a drawing application, using Java and Swing. It has a constant update loop that runs constantly, as long as a boolean variable is set to true. The loop is located inside a thread.
It works fine, but now I want the loop to only run at certain times (only when the mouse is pressed), and otherwise not run. (Thus not wasting memory for nothing).
To stop the loop, I can simply set that variable to false. But my question is, how can I restart the loop after stopping it? Setting that variable back to true will not restart the loop. What would be a good way to do this?
EDIT: My (a little simplified) loop:
public void run(){
int TICKS_PER_SECOND = 50;
int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
int MAX_FRAMESKIP = 10;
long next_game_tick = System.currentTimeMillis();
int loops;
boolean app_is_running = true;
while( app_is_running ) {
loops = 0;
while( System.currentTimeMillis() > next_game_tick && loops < MAX_FRAMESKIP) {
update();
next_game_tick += SKIP_TICKS;
loops++;
}
repaint();
}
}
Use Object.wait to suspend the thread when it isn't running. Have another thread call Object.notify to wake it up from its sleep.
To execute the thread body once every FRAME_RATE ms while being controllable by an externally defined Boolean, the run method could be structured as such:
public void run()
{
long delay;
long frameStart = System.currentTimeMillis();
// INSERT YOUR INITIALIZATION CODE HERE
try
{
while (true)
{
if (active) // Boolean defined outside of thread
{
// INSERT YOUR LOOP CODE HERE
}
frameStart += FRAME_RATE;
delay = frameStart - System.currentTimeMillis();
if (delay > 0)
{
Thread.sleep(delay);
}
}
}
catch (InterruptedException exception) {}
}
Additionally, if you want to eliminate the slight overhead of the constantly running loop (for a mostly inactive thread), the Boolean in the while loop could be replaced with a Semaphore object:
while (true)
{
semaphore.acquire(); // Semaphore defined outside thread with 1 permit
// INSERT YOUR LOOP CODE HERE
semaphore.release();
frameStart += FRAME_RATE;
delay = frameStart - System.currentTimeMillis();
if (delay > 0)
{
Thread.sleep(delay);
}
}
To stop the loop externally use semaphore.acquire(); to restart it use semaphore.release().
How can I read an array in java in a certain time? Lets say in 1000 milliseconds.
for example:
float e[]=new float [512];
float step = 1000.0 / e.length; // I guess we need something like that?
for(int i=0; i<e.length; i++){
}
You'd need a Timer. Take a look at its methods... There's a number of them, but they can be divided into two categories: those that schedule at a fixed delay (the schedule(... methods) and those that schedule at a fixed rate (the scheduleAtFixedRate(... methods).
A fixed delay is what you want if you require "smoothness". That means, the time in between executions of the task is mostly constant. This would be the sort of thing you'd require for an animation in a game, where it's okay if one execution might lag behind a bit as long as the average delay is around your target time.
A fixed rate is what you want if you require the task's executions to amount to a total time. In other words, the average time over all executions must be constant. If some executions are delayed, multiple ones can then be run afterwards to "catch up". This is different from fixed delay where a task won't be run sooner just because one might have "missed" its cue.
I'd reckon fixed rate is what you're after. So you'd need to create a new Timer first. Then you'd need to call method scheduleAtFixedRate(TimerTask task, long delay, long period). That second argument can be 0 if you wish the timer to start immediately. The third argument should be the time in between task runs. In your case, if you want the total time to be 1000 milliseconds, it'd be 1000/array size. Not array size/1000 as you did.
That leaves us with the first argument: a TimerTask. Notice that this is an abstract class, which requires only the run() method to be implemented. So you'll need to make a subclass and implement that method. Since you're operating over an array, you'll need to supply that array to your implementation, via a constructor. You could then keep an index of which element was last processed and increment that each time run() is called. Basically, you're replacing the for loop by a run() method with a counter. Obviously, you should no longer do anything if the counter has reached the last element. In that case, you can set some (boolean) flag in your TimerTask implementation that indicates the last element was processed.
After creating your TimerTask and scheduling it on a Timer, you'll need to wait for the TimerTask's flag to be set, indicating it has done its work. Then you can call cancel() on the Timer to stop it. Otherwise it's gonna keep calling useless run() methods on the task.
Do keep the following in mind: if the work done in the run() method typically takes longer than the interval between two executions, which in your case would be around 2 milliseconds, this isn't gonna work very well. It only makes sense to do this if the for loop would normally take less than 1 second to complete. Preferably much less.
EDIT: oh, also won't work well if the array size gets too close to the time limit. If you want 1000 milliseconds and you have 2000 array elements, you'll end up passing in 0 for the period argument due to rounding. In that case you might as well run the for loop.
EDIT 2: ah why not...
import java.util.Random;
import java.util.Timer;
public class LoopTest {
private final static long desiredTime = 1000;
public static void main(String[] args) {
final float[] input = new float[512];
final Random rand = new Random();
for(int i = 0; i < input.length; ++i) {
input[i] = rand.nextFloat();
}
final Timer timer = new Timer();
final LoopTask task = new LoopTask(input);
double interval = ((double)desiredTime/((double)input.length));
long period = (long)Math.ceil(interval);
final long t1 = System.currentTimeMillis();
timer.scheduleAtFixedRate(task, 0, period);
while(!task.isDone()) {
try {
Thread.sleep(50);
} catch(final InterruptedException i) {
//Meh
}
}
final long t2 = System.currentTimeMillis();
timer.cancel();
System.out.println("Ended up taking " + (t2 - t1) + " ms");
}
}
import java.util.TimerTask;
public class LoopTask extends TimerTask {
private final float[] input;
private int index = 0;
private boolean done = false;
public LoopTask(final float[] input) {
this.input = input;
}
#Override
public void run() {
if(index == input.length) {
done = true;
} else {
//TODO: actual processing goes here
System.out.println("Element " + index + ": " + input[index]);
++index;
}
}
public boolean isDone() {
return done;
}
}
Change your step to be time per number (or total time divided by number of steps)
float step = 1000.0 / e.length;
Inside your for() loop:
try{
Thread.sleep(step);
}catch(InterruptedException e){
e.printStackTrace();
}