To prevent ANR on Android you could implement a Watchdog Timer which would require to have another Thread running and waiting for heartbeats. If you expect your App to have a refresh rate of 30FPS, guard for a refresh rate of lower than 15FPS. This covers also the case when you would have potentially an ANR in the future.
If you know the places where the UI might get stuck for a long time, you can build the watchdog to guard against this (skip current frame for example). If it is to long why are you doing it on the UI? If the action you are performing refers to redrawing the screen you can not do it somewhere else.
Here I made a simple example of a watchdog.
public class MainActivity extends AppCompatActivity {
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread watchdogThread = new Thread(new Runnable() {
long lastT = System.currentTimeMillis();
long lastCount = 0;
long missed = 0;
#Override
public void run() {
while(true){
if (System.currentTimeMillis()-lastT>1500){
if (count == lastCount){
missed++;
}
lastCount = count;
if (missed > 3){
Log.e("test", "Error");
}
lastT = System.currentTimeMillis();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
watchdogThread.start();
startCycleUI();
}
private void startCycleUI() {
//Runs on UI Thread
long lastT = System.currentTimeMillis();
while(true){
if (System.currentTimeMillis()-lastT>1000){
if (count < 10) {
count++;
}
lastT = System.currentTimeMillis();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
When you do not know where to look, is there a way you could build a watchdog timer that simply restarts the application? How can this watchdog timer live beyond the application context?
You can use the example from "Java Source Code Warehouse" project
You have options to:
Monitor the memory in a particular process
Kill the process if they don't return
Check memory usage in the system, scheduling kills/reboots as needed.
Related
I'm trying to make some calculations using Multi threading. At maximum I will have to make 100 different calculations. Even when I tried to balance the start of threads from 10 each time, I am having messages of threads suspending on Log Cat. I think this is killing the performance. When I just launch 10 threads the performance is good.
//launch thread for each accuracy values
executor = Executors.newFixedThreadPool(100/accuracyInterval);
int countThreads = 0;
for(Integer acc: listAccuracies){
Runnable worker = new MyRunnable(acc);
if(accuracyInterval != 10) {
if (countThreads == 10) {
while (threadsDoneCounter < 10) {
//Log.d("THREADS ","WAITING");
}
countThreads = 0;
}
}
executor.execute(worker);
countThreads ++;
}
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated()) {
}
Now the code for MyRunnable
public class MyRunnable implements Runnable {
private final int accuracy;
MyRunnable(int accuracy) {
this.accuracy = accuracy;
}
#Override
public void run() {
Log.d("THREAD " , Integer.toString(accuracy) + " START");
try {
calculatePrediction(accuracy);
} catch (Exception e) {
}
threadsDoneCounter++;
Log.d("THREAD " , Integer.toString(accuracy) + " END");
}
}
What can do make it have a better performance when i have to launch for example 100 threads? what i am doing wrong?
Thanks for the attention,
Regards
I have a memory leak in my android application. It is a simple music player. At the bottom of the screen, I have a TextView which I use to display the elapsed time. It is updated in the thread below.
Each time I change the orientation, the heap size grows. From looking at the DDMS heap updates, it looks like my activity isn't being garbage collected. If, however, I comment out the 6 lines as I have done below, the GC keeps the heap at a fairly consistent size. Could you please let me know what it is that's causing this leak?
private void updateTimerAndSeekBar() {
Thread updater = new Thread() {
SeekBar seekbar = (SeekBar) findViewById(R.id.seekBar1);
TextView timer = (TextView) findViewById(R.id.currentTime);
public void run() {
while (mediaPlayer.isPlaying()) {
// runOnUiThread(new Runnable() {
// #Override
// public void run() {
// timer.setText(msToMins(mediaPlayer.getCurrentPosition()));
// }
// });
try {
seekbar.setProgress(mediaPlayer.getCurrentPosition());
sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
updater.start();
}
Each time you change the orientation, Android creates and starts a new activity. The memory leak is due to the fact that the garbage collector cannot collect the old activity that's no longer needed since the separate thread is still running and - as an inner class - is holding onto the activity.
To get rid of the memory leak, you need to stop and end the separate thread when the activity is destroyed.
boolean stopThread;
private void updateTimerAndSeekBar() {
stopThread = false;
Thread updater = new Thread() {
...
while (!stopThread && mediaPlayer.isPlaying()) {
try {
seekbar.setProgress(mediaPlayer.getCurrentPosition());
sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
updater.start();
}
protected void onDestroy () {
stopThread = true;
super.onDestroy();
}
Can I use a thread for increment a counter and shows it in a frame of Android activity.
Public class MainActivity extendsActivity {
TextView counter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
counter = (TextView) findViewById(R.id.TV_counter);
Thread t = new Thread() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
counter.setText("" + i);
System.out.println("Value of i= " + i);
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
};
t.start();
}
}
I wrote this code, but it run properly in console, but the text view displays i=4 in the terminal, I modified the time to sleep(3000) and the problem persists.
First you don't ever want to put sleep in UI Thread that can lead to unresponsive user interface and that is never good. You should use it just to update your graphics. Try replacing your code with this
Thread t = new Thread() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
final int a = i;
runOnUiThread(new Runnable() {
public void run() {
counter.setText("" + a);
}
});
System.out.println("Value of i= " + i);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
You are going to notice that sleep and for loop is outside UIThread and in your first thread, so basically all of your math is done outside and you just display the results.
This is just a correction of your code and suggestion for further thinking
EDIT: And for you to better understand why your code is not working, you set some value on your TextView, and immediately after you set UIThread to sleep, UIThread blocks instead of giving it time to finish updating graphics, after he finish sleep you set new value, and he never got to update previous one so in the end you see just the last one.
Hope this helps and enjoy your work.
you can use a CountDownTimer, and update your UI in the onTick() method ( this method is executed on the UI Thread):
int i=0;
CountDownTimer timer = new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
// this method will be executed every second ( 1000 ms : the second parameter in the CountDownTimer constructor)
i++;
txt.setText(i);
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
};
timer.start();
I am trying to make view of random text 3 times with time pausing between.
I just can't! It all run all together. I admit I don't know thread subject at all, I just need simple solution.
public void loading3() {
Random randomDouble = new Random();
temp = (double) randomDouble.nextInt(100);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
result.setText(temp + "%");
}
This is the code. I want to use it let's say 3-4 times in a row. How can i do it? I try inside loop or writing same methods in a row but it won't work because it doesn't wait for the first method to end before start the new one.
You should not sleep on the main thread. This can easily be done with a Handler or Timer. Here is an example with a Handler:
private int mCount = 0;
private Handler mHandler = new Handler();
private Runnable mUpdater = new Runnable() {
public void run() {
Random randomDouble = new Random();
temp = (double) randomDouble.nextInt(100);
result.setText(temp + "%");
mCount++;
if (mCount < 3)
mHandler.postDelayed(mUpdater, 1000);
}
}
public void loading3() {
mHandler.postDelayed(mUpdater, 1000);
}
In my app i manage to determine is there connection or not, but i want that application itself try to reconnect 5 times, and every time to increase the interval between to reconnects m i did some code, but its not working, he give me response immediate.
Here is my reconnect class:
public class ReestablishConnection {
Application APP = new Application();
boolean status;
int reconnectInterval = 1000;
int i;
public boolean reconnect(String URL){
Thread timer = new Thread(){
public void run(){
for(i=1;i<6;i++){
if(APP.testConnection(APP.defaultUrl()) == 0){
status = false;
}else if(APP.testConnection(APP.defaultUrl()) == 1){
status = true;
}
try {
sleep(reconnectInterval * i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
return status;
}
}
You create a new thread, which sleeps for a while, but the method which spawned it (reconnect) will return immediately. You should be using a Handler with postDelayed().
Take a look at the answer here:
How to run a Runnable thread in Android?
Sleep is used too often. The correct design is to implement a listener for when a connection is available and respond to listener callback in your UI.