Picasso threads keep running - android

How I am supposed to shut down picasso properly?
Example:
I only have 1 activity, and in this activity in onDestroy, I call shutdown() on all picasso instances(I don't use the singleton one).
But, until this activity gets destroyed, Picasso is keeping the device awake(I start the app, use it, press home, leave the phone for the weekend alone, check it on monday, the battery is dead because Picasso kept the phone awake).
These Picasso threads are still running:
-Picasso-Stats
-Picasso-refQue (twice)
-Picasso-Dispatcher (twice)
Why? Are they supposed to?
What's the best practice for shutting it down? In onStop()? And I should keep a list of unfinished downloads that I might want to retry in onResume()?

As far as i know default singleton instance in picasso cannot be shutdown,
but i solved problem, in 'picasso.java' file at line : 643
found this code:
#Override public void run() {
Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND);
while (true) {
try {
// Prior to Android 5.0, even when there is no local variable, the result from
// remove() & obtainMessage() is kept as a stack local variable.
// We're forcing this reference to be cleared and replaced by looping every second
// when there is nothing to do.
// This behavior has been tested and reproduced with heap dumps.
RequestWeakReference<?> remove =
(RequestWeakReference<?>) referenceQueue.remove(THREAD_LEAK_CLEANING_MS);
Message message = handler.obtainMessage();
if (remove != null) {
message.what = REQUEST_GCED;
message.obj = remove.action;
handler.sendMessage(message);
} else {
message.recycle();
}
} catch (InterruptedException e) {
break;
} catch (final Exception e) {
handler.post(new Runnable() {
#Override public void run() {
throw new RuntimeException(e);
}
});
break;
}
}
}
while (true) have high cpu usage, i decided to change it as follows :
#Override public void run() {
Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND);
while (true) {
try {
// Prior to Android 5.0, even when there is no local variable, the result from
// remove() & obtainMessage() is kept as a stack local variable.
// We're forcing this reference to be cleared and replaced by looping every second
// when there is nothing to do.
// This behavior has been tested and reproduced with heap dumps.
RequestWeakReference<?> remove =
(RequestWeakReference<?>) referenceQueue.remove(THREAD_LEAK_CLEANING_MS);
Message message = handler.obtainMessage();
if (remove != null) {
message.what = REQUEST_GCED;
message.obj = remove.action;
handler.sendMessage(message);
} else {
message.recycle();
}
Thread.sleep(2000);//===> call ever 2 sec to decrease cpu pressure.
} catch (InterruptedException e) {
break;
} catch (final Exception e) {
handler.post(new Runnable() {
#Override public void run() {
throw new RuntimeException(e);
}
});
break;
}
}
}

Related

What's the issue with "Long monitor contention event"

I have the following service code where I launch a thread responsible for dispatching messages are they come in.
public void run() {
while (! Thread.interrupted()) {
try {
Message msg = null;
synchronized (_queue) {
if (_queue.size() == 0) {
_queue.wait(10000);
}
if (_queue.size() != 0) {
msg = _queue.poll();
}
if (msg != null) {
_dispatcher.dispatch(msg);
}
}
}
catch (InterruptedException i) { }
catch (Exception e) { }
}
}
public void add (final Message m){
if (m == null)
return;
synchronized (_queue){
_queue.add(m);
_queue.notify();
}
}
But when this code runs on my android simulator, I get a lot of warnings like the following:
Long monitor contention event with owner method=void com.foo.PrioritizedMessageQueue.run() from PrioritizedMessageQueue.java:58 waiters=0 for 585ms
To me, this seems like the most efficient way of writing a queue processor. When there are not message to process, the processing thread will wait until one is added, and the "add" will notify any waiting thread why a new message is added to the queue. My thought is the dispatching thread won't use minimal resources when no message exists (as it is blocked).
However, there is a reason why android is issuing this warning but I wonder why. It is clearly not happy with my thread being blocked this long but why is that an issue? Isn't this more efficient in that it won't use any CPU cycles while it's waiting?
Also, should I be worried that android may kill my thread because it's been blocked too long? I would hate for my thread to be killed but not the service. If my service is killed, I can handle that, but I can't handle just that one thread being killed.
You should release the lock on the queue before calling _dispatcher.dispatch. Otherwise, the outside thread attempting to call _queue.add is blocked while the worker thread is processing the message.
Adjusting the curly braces is all that's needed. Here's your run thread function adjusted to allow for dispatch to be called after relinquishing the monitor of _queue.
public void run() {
while (! Thread.interrupted()) {
try {
Message msg = null;
synchronized (_queue) { // acquire the queue lock
if (_queue.size() == 0) {
_queue.wait(10000);
}
if (_queue.size() != 0) {
msg = _queue.poll();
}
} // release the queue lock
if (msg != null) {
_dispatcher.dispatch(msg);
}
}
catch (InterruptedException i) {
}
catch (Exception e) {
}
}
}

How to stop this thread?

I implemented this class in my android code
I made the below change in the run method(replaced "true"):
#Override
public void run() {
while (!isInterrupted()) {
try {
// A blocking operation. Initiate a ChatManager instance when
// there is a new connection
pool.execute(new ChatManager(socket.accept(), handler));
Log.d(TAG, "Launching the I/O handler");
} catch (IOException e) {
try {
if (socket != null && !socket.isClosed())
socket.close();
} catch (IOException ioe) {
}
e.printStackTrace();
pool.shutdownNow();
break;
}
}
}
I want to stop this thread before I close the app. So I implemented threadName.interrupt(); method. But this doesn't interrupt the thread.
I am actually confused with the usage of thread pool executor. So I am not sure how to do this efficiently. How can I implement interrupting this thread? When interrupt method is called, I want to close the socket, shutdown the pool and stop the thread.
Thread thread = new Thread () {
boolean isRunning = true;
public void stopThread() {
isRunning = false;
}
#Override
public void run() {
while (isRunning) {
try {
// A blocking operation. Initiate a ChatManager instance when
// there is a new connection
pool.execute(new ChatManager(socket.accept(), handler));
Log.d(TAG, "Launching the I/O handler");
} catch (IOException e) {
try {
if (socket != null && !socket.isClosed())
socket.close();
} catch (IOException ioe) {
}
e.printStackTrace();
pool.shutdownNow();
break;
}
}
}
};
thread.start();
Try this code. and call thread.stopThread() whenever you want the thread to stop.
if you want close an Android thread, you can set a variable to control run(),because run() is end, the thread will be closed.
The code is something like:
final boolean istrue=true;
new Thread(new Runnable() {
#Override
public void run() {
while (istrue){
//TODO your work
}
}
}).start();
}
If you want to close the thread, you only set istrue=false
Just call shutDownNow to close the pool and try interrupt all the threads inside it. You can check the difference in this post:
shutdown() will just tell the executor service that it can't accept new tasks, but the already submitted tasks continue to run
shutdownNow() will do the same AND will try to cancel the already submitted tasks by interrupting the relevant threads. Note that if
your tasks ignore the interruption, shutdownNow will behave exactly
the same way as shutdown.
If you want to interrupt or cancel an specific thread. I suggest you to use submit with Callables, With this, you will me able to work with your Future object, then if want to cancel a task you've given an executor service, you can call cancel(true) on its associated Future. When your task detects an interrupt request, it should preserve the interrupted status by calling Thread.currentThread().interrupt().

Problems delaying the execution of a code in Android

I have implemented an app which can communicates with a metawear device through i2c communication. The problem I have right now is that after sending a write command I need to wait a certain amount of time until I read the values (around 150ms).
The problem I have is that it doesn't wait that specific time. I used TimeUnit, Thread.sleep and wait functions but still doesn't make the delay I want it to execute the next line of code. Here is the function that I have implemented:
#Override
protected void test_application(){
timerModule.scheduleTask(new Timer.Task() {
#Override
public void commands() {
i2cModule.writeData((byte) 0x34, (byte) 0xA0, new byte[]{(byte) 0x98});
//We need to wait >80ms for the ADC to finish the conversion value
// synchronized (this) {
// try {
// wait(150);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//}
try{
TimeUnit.MILLISECONDS.sleep(150);
} catch (InterruptedException e){
e.printStackTrace();
}
//try{
// Thread.currentThread().sleep(150);
//} catch (InterruptedException e){
// e.printStackTrace();
//};
//After waiting 150ms for the conversion time, we read the output value through the I2C line
i2cModule.readData((byte)0x34, (byte)0x00, (byte)4).onComplete(new CompletionHandler<byte[]>() {
#Override
public void success(byte[] result) {
auxvar = result;
}
});
finalvoltage = ((auxvar[0]&0x3F)<<18)|(auxvar[1]<<10)|(auxvar[2]<<2)|((auxvar[3]&0xC0));
diff_volt1 = (float)finalvoltage * 3/16777215;
LineData data = chart.getData();
if (startTime == -1) {
data.addXValue("0");
startTime= System.currentTimeMillis();
} else {
data.addXValue(String.format("%.2f", (System.currentTimeMillis() - startTime) / 1000.f));
}
data.addEntry(new Entry(diff_volt1, sampleCount), 0);
sampleCount++;
}
}, 500, false).onComplete(new AsyncOperation.CompletionHandler<Timer.Controller>() {
#Override
public void success(Timer.Controller result) {
result.start();
}
});
I want it to wait before executing the i2cmodule.readData() function. Here is the capture from the logic analyzer so that you could see that it doesn't wait before reading the data
Does anyone know how to implement this or solve this issue? Thanks anyway.
EDIT: I have changed the writing command to just one line and the new output of the logic analyzer is as follows:
byte[] hello = {(byte)0xA0, (byte)0x98};
i2cModule.writeData((byte) 0x34, (byte) 0x00, hello);
And the new output is at follows:
Generally it is a bad idea to 'wait' for a command to finish if it is asynchronous. You need to make sure that the .writeData() method is finished BEFORE you execute the .readData() method.
There are many ways to do this. I like the listener pattern, but for this you could also use an abstract class construction.
The basic idea is to implement a class (let's call this DataWriter) that invokes an abstract method as soon as the writing of the data is done.
A very basic example would be:
class definition
abstract class DataWriter {
public DataWriter() {
doWritingFunction();
}
private void doWritingFunction() {
//here you do your writing operation
//when it's done it calls:
onWritingDone();
}
abstract void onWritingDone();
}
Then you instantiate your class like this:
DataWriter dataWriter = new DataWriter() {
#Override
void onWritingDone() {
//do data read here
}
};
Never use Thread.sleep() to wait for an asynchronous task to finish, since you never know when it is going to be finished

Puzzle: Bluetooth data send interval shortened by half after each reconnect

I modified the standard Bluetoothchat example to send 4 bytes of data at a time to a bluetooth device every half a second. It works fine if I start the App fresh. However, there is a problem if I reconnect as follows:
While Bluetooth is connected, I click the connect button again on the menu and select the same device. This disconnects the bluetooth (not sure whether this is the right procedure to disconnect). Then, I connect again by selecting the device, and it will be reconnected. After reconnection, a very strange problem appears: instead of sending the data every half a second, it will send the data every quarter a second. If I go through the process again and reconnect, the time interval will become even shorter. It gets to a point that the bluetooth device on the receiving end can't keep up with the data. At this point, the only way out is to kill the app and restart again. Then everything becomes normal, till next time I try to reconnect again.
I have tried different things but nothing appear to fix this. For example, I made sure the thread sending the data is killed when disconnected so no multiple threads are sending the data. I was wondering whether the baud rate changed when reconnected, but then why would the baud rate affect the Thread.sleep(500); statement (which is responsible for controlling the half a second data send). Any help would be greatly appreciated.
Here is the code, the SendClass is created under the MainActivity:
class SendClass implements Runnable {
public void run() {
bytearr[0]=0;bytearr[1]=0;bytearr[2]=0;bytearr[3]=0;
while (!Thread.currentThread().isInterrupted()) {
if (mChatService==null || mChatService.getState()
!=BluetoothChatService.STATE_CONNECTED) {
continue;
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mChatService.write(bytearr);
}
}//end of run
}//end of runnable
Then under STATE_CONNECTED:
case BluetoothChatService.STATE_CONNECTED:
setStatus(getString(R.string.title_connected_to,mConnectedDeviceName));
/*
if(sendingThread!=null){
//sendingThread.stop();
sendingThread.interrupt();
if(D) Log.i(TAG, "after sendingThread");
sendingThread = null;
}*/
sendingThread = new Thread(new SendClass());
sendingThread.start();
break;
As you can see, I tried to kill the thread before creating a new one but that didn't make any difference. Any suggestions?
You are creating a thread that never actually stops, even after you create a new thread and assign to the same variable that particular thread wont stop running.
You need to make sure that the thread will stop after it disconnects.
Here is my suggestion
Change your SendClass to:
class SendClass implements Runnable {
private boolean stopped = false;
public void setStopped(boolean s){
this.stopped = s;
}
public void run() {
bytearr[0]=0;bytearr[1]=0;bytearr[2]=0;bytearr[3]=0;
while (!Thread.currentThread().isInterrupted() && !stopped) {
if (mChatService==null || mChatService.getState() !=BluetoothChatService.STATE_CONNECTED) {
continue;
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mChatService.write(bytearr);
}
}//end of run
}//end of runnable
Then when you start your thread keep the reference to the Runnable so you can call the setStopped(true); like this
SendClass sc = new SendClass();
sendingThread = new Thread(sc);
sendingThread.start();
When you disconnect the bluetooth dont forget to call sc.setStopped(true); so your thread will finish by not going into the while.

android thread while loop not running well

this is my thread:
#Override
public void run() {
Log.d("ConnectionThread","Starting Server Connection");
try {
while(isThereActivityRunning()) {
if(isInternetOn == true){
Log.d("ConnectionThread", "Internet is On. Sending Http request");
results = sendGetMessage();
b.putString("results", results);
receiver.send(2, b);
}
else {
Log.d("ConnectionThread","Internet is Off. Sleeping");
}
ConnectionThread.sleep(timeInterval);
}
} catch (InterruptedException e) {
results = e.toString();
}
Log.d("ConnectionThread","Server Connection Finished");
}
The isInternetOn boolean is from an event listener I've made, and it's value is changed by the state of the internet.
For some reason when the internet is on (isInternetOn == true) it does the if condition and then go to the else condition..
I can't figure out why it is doing this. Thanks!
Not sure I am parsing your question correctly but you need to make sure that the values that you are checking inside of isThereActivityRunning() have been marked as volatile or have been synchronized if it is accessed in multiple threads. Same goes for isInternetOn. If your thread is not seeing this value change and if it is changed by another thread then this is probably the issue. You can also use the AtomicBoolean and other classes to share values between threads.

Categories

Resources