Some Logical error in handler in Android - java

I am beginner in android.
What I want:
Here I am trying to achieve that sub handler should call 10 times of every second of main handler. And that main handler should continue until 20 seconds.
Issue:
To check that i\I have used log but its not working. It goes into sub handler some times 8 times or some times 9 or 10.
Is there any logical error or is there any other better way to achieve this?
Thank you.
My code:
int i=0;
int cont;
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
i++;
cont = 1;
Log.e("main count", i + "");
final Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
if (cont <= 10) {
Log.e("sub count ", cont + "");
cont++;
handler1.postDelayed(this, 100);
}
}
}, 100);
if (!(i == 20)) {
handler.postDelayed(this, 1000);
}
}
}, 1000);

It's difficult to execute code with precise timing using a Handler because you have to measure the time yourself.
It's much easier to use the built-in classes like ScheduledThreadPoolExecutor or Timer. I'd recommend the first as it would require less changes to the code. You should pick one of the scheduleAtFixedRate() or scheduleWithFixedDelay() methods according to your requirements.
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
final ScheduledFuture mainFuture = executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
if (i < 20) {
Log.e("main count ", i + "");
i++;
} else {
mainFuture.cancel(true);// stop after 20 executions
}
},
0, /*initial wait time*/
1, /* time between consecutive runs */
TimeUnit.SECONDS);
final ScheduledFuture subFuture = executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
if (cont < 20 * 10) {
Log.e("sub count ", cont + "");
cont++;
} else {
subFuture.cancel(true);// stop after 200 executions
executor.shutdown();
}
},
100, /*adjust this according to the desired sequencing of the count tasks */
100, /* time between consecutive runs */
TimeUnit.MILLISECONDS);
You could also use a single ScheduledFuture and execute the code for main count after every 10 executions of the sub count code.

Related

Java - Instantiate Runnable Inside Loop

I want to create multiple Runnable object for alarm application which will execute tasks in the time specified by user.
I try to do it inside loop like the following:
ScheduledExecutorService wait;
List<Runnable> listens = new ArrayList<>();
int i;
private void playAlarmOnInit(){
wait = Executors.newScheduledThreadPool(3);
// loop through the tasks to get times
int counts = getDays().size();
for(i = 0; i < counts; i++){
if(!getDays().get(i).isEmpty()) {
Runnable listen = new Runnable() {
#Override
public void run() {
if(!getDays().get(i).equals("Everyday")) {
System.out.println(getDays().get(i) + " " + getTimes().get(i));
} else {
DateFormat format = new SimpleDateFormat("d-M-yyyy");
Date date = new Date();
String time = format.format(date);
System.out.println(time + " " + getTimes().get(i));
}
// System.out.println(" " + getTimes().get(i));
}
};
wait.scheduleAtFixedRate(listen, 0, 1, TimeUnit.SECONDS);
}
}
}
And it does nothing.
Why the code above does not work?
your problem is probably that you use i in your Runnable. At the time your Runnable is being executed, the value of i should be equal counts, so getDays().get(i) in the Runnuble should actually throw a IndexOutOfBoundException. Try to use try-catch and check, if there is an exception. To fix that you should create a new final variable and use it in the Runnable:
if(!getDays().get(i).isEmpty()) {
final int runnableI = i;
Runnable listen = new Runnable() {
#Override
public void run() {
if(!getDays().get(runnableI).equals("Everyday")) {
....
Or you could even store the day as the final variable:
final String day = getDays().get(i);
and use it in the Runnable
maybe the main program closing before threads are started. Add Thread.sleep(5000), after:
wait.scheduleAtFixedRate(listen, 0, 1, TimeUnit.SECONDS);
Thread.spleep(5000)
or maybe your list (getDays) is empty.

Usage of countDown latch in java

Am new to java programming and first time using countDown in java,
My code snippet is,
CountDownLatch latch=new CountDownLatch(rows*columns); //rows -2 , columns -3
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
GUIView view = getView(1, 1);
if(view == null) {
if(ViewColumn(j +1) != null){
latch.countDown(); //EDT
continue;
}
latch.countDown(); //EDT
break;
}
new Thread(new countDownThread(view,latch)).start(); //Where i do some other processing and do countDown
}
}
try {
logger.log("Before countdown await");
latch.await();
logger.log("After countdown await");
}
.........
........
As i read from another post,
One of the disadvantages/advantages of CountDownLatch is that its not
reusable once count reaches to zero you can not use CountDownLatch any
more.
My doubt here is am using the same instance latch , inside the for loop. if CountDownLatch is not reusable what will happen if the first iteration latch.countDown() starts and it became zero by third iteration(The latch.countDown() at third iteration is not valid??).
The problem is :
When i debug the for loop(using eclipse), and when control reaches latch.await(); it just hangs. However, if i just run the application no hang happens.
I don't quite understand usage of countDown latch. Please explain me on the same.
Seems here you don't use multithreading, and all work done in one thread, because of you needn't to use CountDownLatch.
Also latch.await(); hang because it waiting for all count of tasks will be done(seems here it //rows -2 , columns -3 = 6) and call latch.countDown();. Read more about in docs.
Here is simple example of use, where t2 wait for t1:
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String... s){
final CountDownLatch cdl = new CountDownLatch(1);
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
int i = 5;
while(i-- > 0)
System.out.println("t2 wait me");
cdl.countDown();
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("done");
}
});
t2.start();
t1.start();
}
}
When you initialize CountDownLatch with some value for example:
CountDownLatch latch = new CountDownLatch(3);
It basically means that when method:
latch.countDown();
will be fired three times, the class which will use latch will be released from the await method call.
Of course you must ensure that the same instance of latch is used.
For more information go to nice tutorial: http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html

Button To Flash

Hi im trying to get a button to flash, I have tried to change the background with a loop, but not having much luck any suggestions thanks
int count = 0;
while (count < 10000) { // test: boolean test within (..)
if (count % 2 != 0) {
helpt.setBackgroundColor(getResources().getColor(R.color.Blue));
}
else {
helpt.setBackgroundColor(getResources().getColor(R.color.Red));
}
count = count + 1;
}
This will change the colour every one second:
int count = 0; //Declare as instance variable
Activity activity; //Declare as instance variable
//Inside onCreate()
activity = this;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
activity.runOnUiThread(new Runnable() {
public void run() {
if (count < 10000) {
if (count % 2 != 0) {
helpt.setBackgroundColor(getResources()
.getColor(android.R.color.black));
} else {
helpt.setBackgroundColor(getResources()
.getColor(android.R.color.white));
}
count = count + 1;
}
}
});
}
}, 0, 1000);
You dont have any form of delay, of course you wouldn't see it flash. It will run through that loop very quickly. Also for standards you should be using a for loop, not a while. For is explicityly for when you know how many times you are going to run.

Java Android Threads, the same thread works twice

in my app I have a timer and stop/start buttons. Timer works with thread
when I click the button my timer starts working. when I click stop and start it seems like my thread works as 2 parallel threads.
How to stop the first thread and create the second ?
Here is the code
timer = new Thread(new Runnable() {
#Override
public void run() {
final boolean cont = mSharedPreferences.getBoolean("continuesMode", false);
final boolean statemant = !stopedAlgo && !mUserStop;
if(!statemant){
timerMinutes = 0;
timerHours = 0;
}
while(statemant){
time="";
if(timerMinutes>=60){
timerMinutes = 0;
timerHours++;
}
if(timerHours<10)
time = "0" + String.valueOf(timerHours)+":";
else
time = String.valueOf(timerHours)+":";
if(timerMinutes<10)
time += "0" + String.valueOf(timerMinutes);
else
time += String.valueOf(timerMinutes);
HeadSense.this.runOnUiThread(new Runnable(){
public void run(){
boolean state = mContinuousMode && !stopedAlgo && !mUserStop ;
if(!stopedAlgo && cont){
mTfsValue.setText(time);
timerMinutes++;
}
else{
timerMinutes = 0;
timerHours = 0;
}
}
});
try {
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
timer.start();
Of my understanding your first Thread (or second) will never stop because of the following line:
final boolean statemant = !stopedAlgo && !mUserStop;
This is final, and will only be evaluated once and never change. If it evalutes to true when you create the Thread it will stay true and keep running.
You need to declare your boolean statemant as volatile here. What this does is give a hint to the compiler that certain optimizations cannot be taken because this variable is modified by external threads.
Also, you would be interested in this - How to stop a java thread gracefully?

testing code on time interval

Hi I want to run code over a time period. For example i would like my code to do something like this.
for(every 5 minutes until i say to stop)
automatically read in new value for x
automatically read in new value for y
if (x==y)
//do something
if (x!=y)
//do something else
Timer is what you need.
Naive version. You might consider Timer or the quartz scheduler instead.
while (!done) {
try {
Thread.sleep(5 * 60 * 1000);
x = readX();
y = readY();
if (x == y) {
} else {
}
} catch(InterruptedException ie) {
}
}
System.currentTimeMillis(); Returns you the system time in milliseconds, you can use that.
but first, you need some sort of loop.
This is an alternative to Timer 's
public static final int SECONDS = 1000;
public static final int MINUTES = 60 * SECONDS;
boolean quit = false; //Used to quit when you want to..
long startTime = System.currentTimeMillis();
while (!quit) {
if (System.currentTimeMillis() >= (startTime + (long)5*MINUTES)) {
//automatically read in new value for x
//automatically read in new value for y
if (x==y) {
//do something
} else {
//do something else
}
startTime = System.currentTimeMillis(); //reset the timer for the next 5 minutes
}
}
How about:
Runnable runnable = new Runnable() {
public void run() {
// do your processing here
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 5, TimeUnit.MINUTES);
Call service.shutdown() when you want to stop.

Categories