I'm learning about Runnable right now and am a little confused with a code I found and how it's running.
j = 0;
public Runnable test = new Runnable() {
#Override
public void run() {
if (j <= 4) { //this is an if statement. shouldn't it run only once?
Log.i("this is j", "j: " + j);
handler.postDelayed(this, 2000); //delays for 2 secs before moving on
}
j++; //increase j. but then why does this loop back to the top?
Log.i("this is j", "incremented j: " + j);
}
};
When I run this, every 2 seconds j will log from 0 to 4. I don't understand why though, but it does exactly what I need of having a data updated every 2 seconds.
Does run() just keep... running? Which would explain why it keeps looping, kinda. But then if that was the case then even after the if statement finishes j would still be incrementing itself.
Any help in explaining this would help, thanks!
Check out the documentation for Handler.postDelayed(Runnable, long):
Causes the Runnable r to be added to the message queue, to be run after the specified amount of time elapses.
What postDelayed() does is take a Runnable instance and call its run() method after a given delay. It does not resume execution where you left off.
In your case, you are passing this which is a Runnable that checks if (j <=4 )) and if so, posts that same runnable again, thus executing the run() method again.
If you just want a delay after checking if j <= 4, you likely want Thread.sleep() which will sleep a thread for a given amount of time.
A Runnable is just that: a block of code that can be run. The magic happens when you use Runnable's with a Handler, like you are doing here. A Handler will accept Runnable's and call their run() method on the Handler's thread. You tell a Handler to run a Runnable using Hander.post() or Handler.postDelayed(). post() runs the Runnable immediately, postDelayed() runs it after a given amount of milliseconds.
So the run() method is only run once, but this line:
handler.postDelayed(this, 2000);
tells the Handler to schedule running this (that is, this Runnable) after 2000 milliseconds (2 seconds).
Related
This question is for a college assignment.
I want to run a block of code every n*2 seconds (e.g. wait 1 second and run and wait 2 seconds and run and wait 4 seconds and run, etc) up to 5 times.
I currently have something like this.
int timer = 1000;
int tryCounter = 0;
while( !condition() && counter < 5){
doTask();
Thread.sleep(timer);
timer *= 2;
counter++;
}
Although this works, my grade benefits from not using Thread.sleep(). I figured out using a ScheduledThreadPoolExecutor with a fixed rate would be one way to go but I cannot get it to work due to the fact that the interval is not actually fixed.
This is for a theoretical Distributed System with high concurrency capabilities so what matters is the high scalability.
I could get away with Thread.sleep() if there was really no benefit or a viable way of doing this by writing it on my report. So does anyone have any insight on this?
It is possible to schedule tasks with ScheduledExecutorService combined with some logic. The .schedule argument lets you specify a time unit to use. You can declare a variable that can handle the increment you are trying to do.
int timer = 1000;
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run()
{
//Move your code you want to implement here
}
};
//Increment your variable
while(!condition()) {
for(int i = 0; i < 5; i++) {
service.schedule(runnable, timer, TimeUnit.SECOND);
timer *= 2;
}
}
Moving your code execution within the runnable block and then scheduling it within a for loop where the timer is incremented should accomplish the effect you are going for. Hope that helps!
i want to terminate some process after some time if that process will not responded
i used this code but i am not able to achive the same
long start = System.currentTimeMillis(); long end = start +60000;
1 while (System.currentTimeMillis() < end)
2 {
3 Connection.execute(function); // execute
4 break; // break if response came
5 }
6 if(System.currentTimeMillis() > end)
7 {
8 close connection; // close connection if line no 3 will not responded
9 }
kindly help me on the same
As the call Connection.execute() is blocking, so main thread will be blocked until it executes, SO in that case if we want to close the connection when the main thread is blocked , we have to close connection in some other thread. May be we can use Timer & TimerTask in this case. I tried to write some code as below, May be you can some thing like that.
Timer timer = new Timer();
while (System.currentTimeMillis() < end) { //In any case, this loop runs for only one time, then we can replace it with IF condition
CloseConnectionTask task = new CloseConnectionTask(Connection);
timer.schedule(task, end); // Task will be excuted after the delay by "end" milliseconds
Connection.execute(function); // execute
task.cancel(); //If the excute() call returns within time ie. "end" milliseconds, then timerTask will not get executed.
break; // break if response came//
}
timer.cancel(); // If you have no more scheduling tasks, then timer thread should be stopped.
Below is TimerTask implementation:
class CloseConnectionTask extends TimerTask {
private Connection con;
public CloseConnectionTask(Connection con) {
this.con = con;
}
#Override
public void run() {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Note: I have one more thing to say, In your while loop, If the call to Connection.execute() successful, then you break from the loop. So what I have observed, In any case your loop is executing only once, If this is the case, then you should use IF(again its what I have seen in the provided code, you requirement may be different). Hope it may help you. If you have other thoughts on this, please share. My answer is based on this link, Good info. is there.
this way it will not help
i think you should implement thread to achieve that
and this a normal thread program
class Counter implements Runnable {
private int currentValue;
public Counter() { currentValue = 0; }
public int getValue() { return currentValue; }
public void run() { // (1) Thread entry point
try {
while (currentValue < 5) {
System.out.println(Thread.currentThread().getName() + ": " + (currentValue++)); // (2) Print thread name.
Thread.sleep(250); // (3) Current thread sleeps.
}
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + " interrupted.");
}
System.out.println("Exit from thread: " + Thread.currentThread().getName());
}
}
//_______________________________________________________________________________
public class Client {
public static void main(String[] args) {
Counter counterA = new Counter(); // (4) Create a counter.
Thread worker = new Thread(counterA, "Counter A");// (5) Create a new thread.
System.out.println(worker);
worker.start(); // (6) Start the thread.
try {
int val;
do {
val = counterA.getValue(); // (7) Access the counter value.
System.out.println("Counter value read by " + Thread.currentThread().getName()+ ": " + val); // (8) Print thread name.
Thread.sleep(1000); // (9) Current thread sleeps.
} while (val < 5);
} catch (InterruptedException e) {
System.out.println("The main thread is interrupted.");
}
System.out.println("Exit from main() method.");
}
}
and the output is
Thread[Counter A,5,main]
Counter value read by main thread: 0
Counter A: 0
Counter A: 1
Counter A: 2
Counter A: 3
Counter value read by main thread: 4
Counter A: 4
Exit from thread: Counter A
Counter value read by main thread: 5
Exit from main() method.
My question is even though the worker thread was started initially before the Main thread enters it's try block, Main thread execution starts first and then when the Main thread goes to sleep child thread gets into action.
As this picture(taken from "A Programmer's Guide To Java SCJP Certification : A Comprehensive Primer 3rd Edition"
Author: Khalid A Mughal, Rolf W Rasmussen) depicts that when the start method is called on the thread it returns immediately.
Please explain this point that why on invoking start method it return immediately and does the thread get starts on calling the start method. As here on calling the start method it doesn't invoke run method of the class. So when does actually the thread starts ?
Also explain this " the call to the start() method is asynchronous."
there are three things that you are missing in your overall analysis.
Call to thread's start method is sequential not parallel. Its the call to run method of Thread that is concurrent. So if you have 5 statements in main method that call start, the 5ht is not going t be called first. Thats the 'happens before' guarantee that JVM specs give you. However the run method of 1 first may get called before or after the call to the second start statement. This depends as its more of a CPU time slicing issue rather than program execution.
When more than 1 thread runs in your program the order of output is in-deterministic. That's because they run in parallel. You can never be sure that the same program will run in same order on two machines or even in two runs on the same machine. In your question you have posted only 1 output. Run the program like 20 times one after another and match the output. I am sure 2 or 3 would be entirely different.
Finally, you are basing your analysis on the order or execution of your concurrent code. That's the biggest blooper programmer make. Concurrent programs are never intended to run in a specific order or sequence. Just try to make your Runnable work an atomic mutually exclusive task (mutually exclusive to the rest of program or even to other Runnables) and track its own execution. Dont mix Threads together.
You cannot directly enforce which Thread is executed/running when. Once you start it, it's handled on lower level(usually by OS) and the results may differ on different machine or even in different execution. If you need more control, you need to use some synchronization mechanism.
The thread is isn't started synchronously underneath the call to start(). It happens later (asynchronously). In other words, just because you called start() doesn't mean the thread has started.
They why and how are all implementation details, that may depend on JVM and/or OS implementations.
I have a Thread that runs in my test app with a while loop inside the thread. While the while loop is running i want to execute a method from within this while loop every 30 seconds. Inside the while loop, don't want to sleep the thread or stop the loop, it must run and every 30 seconds call the method.
Thread myThread = new Thread() {
#Override
public void run() {
//my code that runs with a loop
//while loop here that runs and needs to execute method every 30 seconds, if condition met continue else break;
};
myThread.start();
}
To wait, you can use
Thread.sleep(milliseconds);
For documentation, see here
If you wait for 30 seconds in your loop, it happens every 30 seconds + execution time of your function. As long as your function call only takes milliseconds this is as precise as doing it in a more complex way.
If you want your loop to keep running but you do not want to launch a new Thread, you can use the current Time:
long lastCall = 0;
while(bla) {
if(System.currentTimeMillis() - lastCall > 30000) {
lastCall = System.currentTimeMillis();
callTheFunction();
}
}
Place it where thread is executed:
Thread.sleep(30000);
I need to check how many events are detected within 2 seconds. I have the timer working and I have everything else working...but I ran into a problem: the loop only checks one time, per second and I can't seem to figure out how to fix that. I need it to check constantly during these two seconds to see how many events there were in total!
Here is what I have:
int seconds = 0;
System.out.println("Seconds: " + seconds);
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {}
seconds++;
System.out.println("Seconds: " + seconds);
//This needs to be looping the whole time.
//But right now, it's being blocked and only checked once
if(eventDetected() && seconds <= 2){
events++;
}
}
So you can see my problem. I can't split them up because then the second timer would run, and THEN eventDetected() would be checked. I need it to check constantly DURING the two second timer...so I basically need both things to happen at once. Is there any way I can do this?
Thanks for any help ahead of time!
I think your design pattern needs work -- I don't know what type event you're looking to detect, but no matter how short your sleep time is, there's a chance you could miss an event using the current pattern. Here's what I suggest:
Have eventDetected() increment your events counter. That way, you won't miss an event.
Then, you just need a way to turn on and off listening (and perhaps resetting the event counter). If you're sure that in you're current pattern you are really in a different thread that won't block your eventDetected() method, you could set a flag to check. For example:
When you want to start listening:
listenForEvents = true;
In eventDetected():
if (listenForEvents) { events++; }
When you want to stop listening (for example, after your Thread.sleep() call):
listenForEvents = false;
With multithreading, make sure to watch out for concurrency issues checking and setting the variables, of course.
I would tell you what kind of event I have to keep track of but then I'd have to kill you :D
Answered my own question. Hopefully this will help anyone else out who has a similar problem at some point! I looked up multithreading a bit...
I created a new class EventTimer which implements Runnable, with a public field for seconds:
public class EventTimer implements Runnable{
int seconds;
static int timerThreadCount = 0;
Thread t;
public EventTimer() {
timerThreadCount++;
this.seconds = 0;
t = new Thread(this, "Event Timer");
t.start(); // Start the thread
}
#Override
public void run() {
// TODO Auto-generated method stub
while(seconds < 2)
{
//Wait 1 second
try {
Thread.sleep(1000);
}
catch(Exception e) {
System.out.println("Waiting interupted.");
}
seconds++;
System.out.println("Seconds: " + seconds);
}
}
}
Then I used an instance of the EventTimer, and used a while loop & if statement to solve my problem.
EventTimer t = new EventTimer();
while(t.seconds < 2){
if(eventDetected()) events++;
}
It was actually quite simple! I realize that each iteration of my loop of operation (since the entire code piece above is inside an infinite loop) will create a new EventTimer thread and I will eventually run into memory problems however. How would I close/end a thread after the timer has reached 2 seconds?