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) {
}
}
}
Related
I write an app with a button, when the button is clicked, the following method will be invoked:
public void click(View view) {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
So, apparently, this will cause an anr after a next input event come. I thought this click method handling the input event will not cause the finishInputEvent method in InputEventReceiver class be called, but I'm wrong, finishInputEvent is still called whether the click method returns or not. finishInputEvent method in InputEventReceiver class is like this:
public final void finishInputEvent(InputEvent event, boolean handled) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to finish an input event but the input event "
+ "receiver has already been disposed.");
} else {
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
if (index < 0) {
Log.w(TAG, "Attempted to finish an input event that is not in progress.");
} else {
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
nativeFinishInputEvent(mReceiverPtr, seq, handled);
}
}
event.recycleIfNeededAfterDispatch();
}
I thought nativeFinishInputEvent will remove one item in queue in input system so that anr will not be caused, but now that nativeFinishInputEvent still be called, why will anr still be caused? how input system konw the input event is not handled?
All Android UI events are handled by a single thread for a given application. By putting that thread to sleep, you are preventing the thread from handling further events, and the system detects that there are events in the queue that are not being handled, hence the ANR. As a rule, you should never sleep in the UI 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().
I am doing an Android app to process images in real time, and I don't know which is the most efficiently way to process these frames.
I launch acquisition process in a thread like this:
/**
* Thread to open camera acquisition process
*/
private static class CameraHandlerThread extends HandlerThread {
Handler mHandler = null;
CameraHandlerThread() {
super("CameraHandlerThread");
start();
mHandler = new Handler(getLooper());
}
synchronized void notifyCameraOpened() {
notify();
}
void openCamera() {
mHandler.post(new Runnable() {
#Override
public void run() {
try {
mCamera = Camera.open(cameraUsed.ordinal());
} catch (RuntimeException e) {
Log.e(TAG, "failed to open front camera");
}
notifyCameraOpened();
}
});
try {
wait();
} catch (InterruptedException e) {
Log.w(TAG, "wait was interrupted");
}
}
}
I reach high frame rates (25 fps more and less) and my process task are about 300 ms. Which is the best and the fastest way to launch these tasks? In other thread? In main thread?
Thanks
There are following things that you should keep in mind
the number of processors on your android device
amount of RAM available
the most efficient would be when
number of threads == number of processors
but the more the threads the more the RAM required.
So you should decide depending on available RAM and CPUs.
btw, Camera.open is a blocking call, so put it in a thread, that's more efficient, but I hope you're not processing images under Camera.open, because in that case, threads or no threads doesn't matter.
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;
}
}
}
I cant figure it out.
For what ever reason, this thread's code is actually running on the UI thread.
If i break point it the UI stops. or Sleep it, UI stopped. and hence network activity is unallowed as its on the "ui" thread.
Ive not used Async task, because I am unaware of the proper way of looping it. (calling a new instance of it in onPostExecute seems like bad practice, and as if async is for one off tasks.
I extend Thread.
public class SyncManager extends Thread {
public SyncManager(Context context){
sdb = new SyncManagerDBHelper(context);
mContext = context;
}
#Override
public void run() {
while(State == RUNNING) {
try{
SyncRecords(); // Break point here = UI freeze.
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(10000); // So also causes UI freeze.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void startThread() {
Log.i("SyncManager", "start called");
if((State == PAUSED || State == STOPPED) && !this.isAlive() )
{
State = RUNNING;
run();
}
}
ANd from my Activity I call
sm = new SyncManager(this);
sm.startThread();
You should use Thread.start() to start any new thread.
As far as I know calling run() directly will not cause the system to actually launch a new thread, hence your blocking UI.
Change your startThread() method to the following and it should then work:
public class SyncManager extends Thread {
public void startThread() {
if((State == PAUSED || State == STOPPED) && !this.isAlive()) {
State = RUNNING;
start(); // use start() instead of run()
}
}
}
Read here for more specific information from the Java revisited blog.