I'm trying to use semaphores to make a thread waiting for something happening outside it with a semaphore, but I don't know why it is not working. Probably is something I don't know about Android semaphores, because I already used the same "way to operate" with some real time operating system (such as FreeRTOS and MXLite) and it works fine.
Practically I have a thread that is running a service each time it executes a while loop inside its run() method. The service execute some long operation and then die, I just want the thread not to run a new service before the previous one has finisched.
The code looks like that (condLog is just a function that doeas a Log.i with the string passed if a DEBUG define is true):
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
startScheduler(msg);
}
};
private static boolean serviceRunning = false;
private static Context context; // context is set in the main class contructor
private executeScheduledAction myThread = new executeScheduledAction();
private void startScheduler(Message msg) {
condLog("startScheduler- message received...");
myThread .releaseSemaphore();
}
private final class executeScheduledAction extends Thread {
private final static int MAX_CONCURRENT = 1;
private Semaphore semaphore = new Semaphore(MAX_CONCURRENT, true);
public executeScheduledAction () {}
public void releaseSemaphore() {
semaphore.release();
condLog("releaseSemaphore - Semaphore released, semaphore permit: " + semaphore.availablePermits());
}
#Override
public void run() {
condLog( "executeScheduledAction - thread started...");
serviceRunning = true;
while(serviceRunning ){
try {
condLog( "executeScheduledAction - taking semaphore, semaphore permits: " + semaphore.availablePermits() );
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
condLog("executeScheduledAction - semaphore taken, running service");
// HERE RUN THE SERVICE
}
condLog( "Thread finished...");
}
}
THe first call myThread.start method. As I expected, the semaphore is taken the first time and the service is correctly launched. At the end, service send a message to an handler that call executeScheduledAction.release...and this is what I obtain in the Logcat:
executeScheduledAction - thread started...
executeScheduledAction - taking semaphore, semaphore permits: 1
executeScheduledAction - semaphore taken, running service
executeScheduledAction - taking semaphore, semaphore permits: 0
startScheduler - message received...
releaseSemaphore - Semaphore released, semaphore permit: 2
Why is it 2 and not 1? it looks like I'm not release the same semaphore I'm acquiring...
Really, any help would be helpfull and appreciated.
Thank you all very much
Cristiano
Semaphore has to go negative to be blocking. In this case you can use a CountDownLatch. If I have not misunderstood you, it should suit better your needs.
Related
I have an App (Client) that performs remote calls using AIDL to a second App (Server). Each call to through the Binder is executed in the Server app in a different thread (TID) as designed by AIDL solution.
Is it possible to make all calls executed in the Server app be executed in just one thread? We have control over all callers (Client apps) and they will perform call in a serial mode and we don't need Server app perform the calls in a multithread way.
So, if the Client App 1 performs a remote call to a method that takes 30 seconds and before it, a second Client App 2 performs a call to the same method (or even other method) we want this second call be executed in the same Thread of the first call.
Messenger is not an option for now.
=== Updated ====
Message is not an option (for now). Here more details: We have a service with 2 type of binders: a) TransacionManager (tm) and DAOImpl (dao).
We first do a call to tm.begin() in the client and even its processed synchronously, on the Service side its is executed in a thread from Thread Pool (android aidl code). This thread TID #1 performs the begin transaction command in SQLite database.
Then we do a call to dao.selectNextId() - synchronously - and in the Service it is executed in the TID #2. In the selectNextId() method we check if the database is inTransaction and it returns false.
To confirm that the threads was the problem, we put everything in a single call to another binder (allDAO). So when we call allDAO.do() it runs on the Service side in another thread TID #3 and performs begin transc and insert very well.
Not sure if the problem is SQLite that manage different threads as separated requests (how to deal with)... We just want the Service (using aidl) perform every call from any clients in a same single thread everytime.
I was working with Mario on this issue and using the #pskink's code snippet we solved the multithreading issue.
The issue was solved redirecting all aidl calls to the main thread. To do this, we used a Handler thats receives the MainLooper and a Runnable that extends CountDownLatch.
The code of our solution bellow:
// SyncHandler.class
public class SyncHandler {
private SyncRunnable mRunnable;
public SyncHandler() {
super();
}
public SyncHandler start(#NonNull SyncRunnable runnable) {
mRunnable = runnable;
final Looper looper = Looper.getMainLooper();
Handler handler = new Handler(looper);
handler.post(mRunnable);
try {
mRunnable.await();
} catch (InterruptedException e) {
Log.e(this, "Error when SyncHandler was awaiting.", e);
}
return this;
}
public static class ReturnValue<T> {
public T value;
}
}
// SyncRunnable.class
public final class SyncRunnable extends CountDownLatch implements Runnable {
private Runnable mRunnable;
public static SyncRunnable create(Runnable runnable) {
return new SyncRunnable(runnable);
}
private SyncRunnable(Runnable runnable) {
super(1);
mRunnable = runnable;
}
#Override
public void run() {
Log.d(this, "SyncRunnable.run() executed on thread: " + Thread.currentThread());
mRunnable.run();
countDown();
}
}
//And the database call:
// TransactionManager.class
public synchronized void begin(final int ownerHashCode, String ownerName) throws RemoteException {
SyncHandler handler = new SyncHandler().start(SyncRunnable.create(new Runnable() {
#Override
public void run() {
if (mOwner == null) {
mOwner = ownerHashCode;
for (Database database : mDatabases) {
database.beginTransaction();
}
} else if (mOwner == ownerHashCode) {
throw new DbTransactionException("Error: TransactionOwner == owner");
}
}
}));
}
// DaoHelper.class
public synchronized long insert(Dao dao) {
final SyncHandler.ReturnValue<Long> value = new SyncHandler.ReturnValue<>();
SyncHandler handler = new SyncHandler().start(SyncRunnable.create(new Runnable() {
#Override
public void run() {
Log.d(DaoHelper.this, "db.inTransaction: " + mManagerDb.getDatabase().inTransaction());
value.value = mManagerDb.getDatabase().insert(mTable, null, mContentValues);
}
}));
return value.value;
}
I'm very new to Android programming so pls excuse my ignorance...
I'm trying to do simple Android app:
User presses a button, starts postDelayed job and then waits on conditional var
after timeout the postDelayer job should signal
private final static long TIMEOUT = 10000;
private Handler mHandler;
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mHandler = new Handler();
...
}
private void timeOutSignal() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d(">> ", "---> timeout notify");
lock.lock();
try {
condition.signal(); // releases lock and waits until doSomethingElse is called
} finally {
lock.unlock();
}
}
}, TIMEOUT);
}
public void buttonClick(View view) {
timeOutSignal();
Log.i("???", "... WAIT");
lock.lock();
try {
condition.await();
} catch (InterruptedException e) {
// todo
} finally {
lock.unlock();
}
Log.i("???", "... WAIT DONE !");
}
What happens is that buttonClick() is stuck waiting and I'm not even seeing the "---> timeout notify" message after timeout...
What I'm doing wrong ?
EDIT: Tried to fix messed up example...
You can't do what you're trying to do. Handlers run on Looper threads. Handlers that are created with the default constructor will use Looper thread that it is currently running in. In this case, it is the main Looper thread (or UI thread). So, you're locking on the UI Thread and the Handler unlocks on the UI Thread, but it will never reach that point because you're blocking the UI Thread.
Also, at no point do I see you actually calling the method that posts to the Handler.
I have a simple Activity with two buttons "On" and "Off". I want start changing color of background in cycle with button "On" and stop this with button "Off". Also I need to have red color by click on "Off" button. I have wrote simple programm and everything is fine, but I can't understand one thing. Why the last color not always red? If I use code in main threads cycle
Thread.sleep(100);
or
Thread.sleep(1000);
I always have red color, but if I set
Thread.sleep(10);
I have random last color. Why??
Thank you !!
I have this code:
public class MyActivity extends Activity {
final Handler myHandler = new Handler();
private int randColor;
final Runnable updateColor = new Runnable() {
public void run() {
final Random random = new Random();
randColor = Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255));
mRelativeLayout.setBackgroundColor(randColor);
}
};
private ColorChanger myThread;
class ColorChanger extends Thread {
private volatile boolean mIsStopped = false;
#Override
public void run() {
super.run();
do
{
if (!Thread.interrupted()) {
myHandler.post(updateColor);
}
else
{
return;
}
try{
Thread.sleep(100);
}catch(InterruptedException e){
return;
}
}
while(true);
}
public void stopThis() {
this.interrupt();
}
}
private RelativeLayout mRelativeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
}
public void onflagClick(View view) {
myThread = new ColorChanger();
myThread.start();
}
public void onflagoffClick(View view) throws InterruptedException {
myThread.interrupt();
if(myThread.isAlive())
{
try {
myThread.join();
} catch(InterruptedException e){
}
}
else
{
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
}
}
I agree with the previous answer-ers, but propose a different solution.
First let me say that I recommend you stop using Runnables. In general posting a Runnable to a Handler is less efficient then sending a Message, although there are very rare exceptions to this rule.
Now, if we send Messages, what should we do? What we basically want to do is keep doing whatever we're doing until a condition is hit. A great way to do this is to write a Message Handler that receives a Message, does our work (setting the color), checks if we should keep going, and if so schedules a new Message in the future to do more work. Let's see how we might do this.
Assume the code below is inside an Activity.
private static final int MSG_UPDATE_COLOR = 1;
private static final int DELAY = 10; //10 millis
private final Object mLock = new Object();
private boolean mContinue = true;
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_COLOR:
synchronized (mLock) {
if (mContinue) {
setColor(Color.rgb(random.nextInt (255), random.nextInt (255), random.nextInt (255)));
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_COLOR, DELAY);
} else {
setColor(Color.RED);
}
}
break;
}
}
}
}
public void onflagClick(View view) {
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
public void onflagoffClick(View view) throws InterruptedException {
synchronized (mLock) {
mContinue = false;
}
// cancel any pending update
mHandler.removeMessages(MSG_UPDATE_COLOR);
// schedule an immediate update
mHandler.sendEmptyMessage(MSG_UPDATE_COLOR);
}
Okay, so, what is happening here. We've created a Handler that will do all the color updates. We kick that off when our start event happens. Then the Message schedules a new message (and therefore color update) in ten milliseconds. When the stop event happens we reset a flag that the message handler reads to determine if a new update should be scheduled. We then unschedule all update messages because it might be scheduled for several milliseconds in the future and instead send an immediate message that does the final color update.
For bonus points we eliminate the use of a second thread which saves resources. Looking carefully I've used synchronized blocks, but these are actually unnecessary because everything is happening on the main thread. I included these just in case someone was changing mContinue from a background thread. Another great point of this strategy is that all color updates happen in one place in the code so it is easier to understand.
When you post to Handler, it will run your Runnable at some given time in the future. It is not immediate. It also works in a queue so the more times you post to Handler you are going to stack up the commands that will all get executed in order eventually.
You're facing a race condition because with Thread.sleep(10), the program is most likely stacking up a lot of Runnables to execute. They will run regardless of whether or not your Thread is running because they've been queued up to run on the main thread. Thread.sleep(100) or Thread.sleep(1000) doesn't have this issue simply because you're giving the system enough time to execute all color commands. However, it is still possible to have this issue if you pressed the off button at just the right time.
As DeeV told you, Handler sends Runnables to a Looper that is basically a Thread looping inside processing messages or runnables in each loop. You are queuing messaged to the main Looper and then you are sleeping your worker Thread. Its possible that you are sending for example 2 runnables in a row between each loop of your worker thread, but the main looper has only executed the last one so you cannot see each color as you want.
If you want a simple solution to make it work, you can use an Object or a CountDownLatch to synchronize your main Looperwith your worker Thread.
For example: Just before you will sleep your worker Thread you can do the next thing myLockObject.wait()
Then, you should change post(Runnable) to sendMessage(Message). In handleMessage from your Handler you can do myLockObject.notify() (Keep in mind that handleMessage will be executed inside the Looper that you have created your Handler or you can specify any Looper you want explicity). To obtain a new Message you should use myHandler.obtainMessage().
This will make your worker Thread wait your main Looperto process your runnable just before you wait X time until you post next color. Obviously you should create your new Object as a field of your Activity for example:
private myLockObject = new Object()
I have to run a bit of code in the background every one second, the code will call a webservice which searches a database and returns a value to the application. My question is which method would be the most effective to do this? I have read up on Timers, Threads, AsyncTask and Services and each seem to have their pros and cons. Please can someone tell me which would be the best to use considering execution time and battery life.
Thanks
Update:
I decided to use Aysnc task to run my code in the background while using a TimeTask to trigger the AsyncTask at regular intervals. This way the operation is destroyed when I leave that particular activity
You should use the service to do the background operation but in your case you want to run code in 1 sec here is the example of service using handler it call in every 1 sec.
public class YourService extends Service {
private static final String TAG = "Your Service";
private final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onDestroy() {
super.onDestroy();
// Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
handler.removeCallbacks(sendUpdatesToUI);
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
/// Any thing you want to do put the code here like web service procees it will run in ever 1 second
handler.postDelayed(this, 1000); // 1 seconds
}
};
#Override
public void onStart(Intent intent, int startid) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);//1 second
Log.d(TAG, "onStart");
}
}
and service can't run every time android idle the service within 3 or 4 hr i suggested you to use the foreground service to use your process long running.
For operations like this I tend to use a Service component. for the task itself i use an AsyncTask which will wait a set time before it repeats itself (using a while loop).
You will have to create a new Thread so that the call don't lock up the device if the call takes longer than expected. The AsyncTask is an easy way to use multithreading, but it lacks the functionality of repeating tasks. I would say that you are best of either using a Timer or the newer ScheduledExecutorService.
If you chose to use the Timer you create a TimerTask that you can hand it. The ScheduledExecutorService takes a Runnable instead.
You might want to wrap the thread in a Service (The Service does not provide a new Thread), but this is not always necessary depending on your needs.
As suggested in comment, you can also use the Handler.postDelayed(). Although you still need to create a new thread and then call Looper.prepare() on it:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
(Code from Looper docs)
Also; calls to a webservice every second seems way too frequent, especially if the user is on a slow connection or there are data that needs to be transferred, try to reduce the calls as much as possible.
I think it's not only one solution, so it's up to you. You can try start thread with this run method:
private final int spleeptime = 1000;
public boolean running;
#Override
public void run() {
while (running) {
try {
int waited = 0;
while ((waited < spleeptime)) {
sleep(100);
waited += 100;
}
} catch (InterruptedException e) {
} finally {
// your code here
}
}
}
I have created IntentService with infinite loop inside the onHandleIntent then add static methods start,resume,pause,stop to directly call it within my Activities.
The scenario is, inside the infinite loop, I am calling callback methods which is creating a new thread to execute long process.
The problem is, I am worrying about continuously creating Threads due to infinite loop. I am pretty sure that there is better way to manage it. I am thinking of ThreadPool or something enable to use only one thread in a sequential manner. So that, I am saving time,memory,overheads etc..
OTHER APPROACH ARE VERY WELCOME. Ask me other information as needed. Then, I will update here.
Here are my codes(take a look at SampleCallback):
IntentService
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class SampleCallbackIntentService extends IntentService {
private final String LOG_LOGCAT_TAG = "SampleCallbackIntentService";
private Handler _handler;
public SampleCallbackIntentService(String name) {
super(name);
}
#Override
public void onCreate() {
super.onCreate();
// initialize variables for pause & resume thread
_mPauseLock = new Object();
_mPaused = false;
_mFinished = false;
// initialize handler to switch to UI/Main thread
_handler = new Handler()
{
#Override
public void handleMessage(final Message msg)
{
_callback.doSomethingFromUIThread(msg);
}
};
}
private final SampleCallback _callback = new SampleCallback() {
#Override
public void doSomethingFromCurrentThread(final Object object) {
new Thread(new Runnable() {
#Override
public void run() {
//do long running process.
// I will access object here.
}
}).start();
}
#Override
public void doSomethingFromUIThread(final Message msg) {
//may update UI here.
}
};
private final int CALLBACK_MESSAGE = 1;
#Override
protected void onHandleIntent(Intent arg0) {
Log.i(LOG_LOGCAT_TAG, "loop started");
while (!_mFinished) {
// do stuff here
// create the object variable. Then pass to callback method
_callback.doSomethingFromCurrentThread(object);
// process and create the result to pass
String someResult = "some result here";
_handler.sendMessage(_handler.obtainMessage(CALLBACK_MESSAGE, someResult));
synchronized (_mPauseLock) {
while (_mPaused) {
try {
Log.i(LOG_LOGCAT_TAG, "loop paused");
_mPauseLock.wait();
Log.i(LOG_LOGCAT_TAG, "loop resumed");
} catch (InterruptedException e) {
Log.e(LOG_LOGCAT_TAG, "error occured on pause", e);
}
}
}
try {
//using sleep here might be not good design.
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(LOG_LOGCAT_TAG, "error occured on sleep", e);
}
}
Log.i(LOG_LOGCAT_TAG, "loop ended");
}
private static Object _mPauseLock;
private static boolean _mPaused;
private static boolean _mFinished;
public static void start(Context context) {
Intent service = new Intent(context, SampleCallbackIntentService .class);
if(context.startService(service)==null) {
Log.e(LOG_LOGCAT_TAG, "Service cannot be started");
} else {
Log.i(LOG_LOGCAT_TAG, "start() called");
}
}
/**
* Call this on pause.
*/
public static void pause() {
Log.i(LOG_LOGCAT_TAG, "pause() called");
synchronized (_mPauseLock) {
_mPaused = true;
}
}
/**
* Call this on resume.
*/
public static void resume() {
Log.i(LOG_LOGCAT_TAG, "resume() called");
synchronized (_mPauseLock) {
_mPaused = false;
_mPauseLock.notifyAll();
}
}
public static void stop() {
if(_mPauseLock == null) return;
synchronized (_mPauseLock) {
Log.i(LOG_LOGCAT_TAG, "stop() called");
_mFinished = true;
}
}
}
SampleCallback
import android.os.Message;
public interface SampleCallback {
public void doSomethingFromCurrentThread(final Object object);
public void doSomethingFromUIThread(final Message msg);
}
UPDATES1
I am using location api aside from google api. I will create a android library project and use that api to get the latest location (e.g. every 2secs) in the background.
On the application side, just need to call static methods to use it (e.g. start(context, callback), pause(), resume(), stop()). It has callbacks to obtain the location. After obtaining the needed information from the location object, I will create a new thread to call my own created callbacks (which implemented by the application side).
You can use AsyncTask instead of creating a new thread every time? AsyncTask manages a fixed pool of threads (or one background thread - depending on Android version) and allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
However I wonder why do you need to create an infinite loop inside the onHandleIntent method? By doing that you prevent your IntentService from receiving further Intents. Since in IntentService:
All requests are handled on a single worker thread -- they may take as
long as necessary (and will not block the application's main loop),
but only one request will be processed at a time.
I think you want to execute some long-running code out of the UI thread in the IntentService. But that doesn't require the creation of an infinite loop in the IntentService worker thread. Just send the requests as needed to the IntentService using Context.startService(Intent) call. If you want IntentService to send back some result or just call a callback in the UI thread you can pass a Messenger (or a ResultReceiver) object with the Intent.
Activity:
final Handler uiHandler = new Handler(Looper.getMainLooper());
private void postTask() {
Intent intent = new Intent("com.yourservice.DOACTION");
intent.putExtra("messenger", new Messenger(handler));
intent.putExtra("object", YourObject()); // pass other Parcelable objects
startService(intent);
}
IntentService:
protected void onHandleIntent(Intent intent) {
Messenger messenger = intent.getParcelableExtra("messenger");
YourObject object = intent.getParcelableExtra("object");
//... do work here ...
Message msg = Message.obtain();
msg.what = CALLBACK_MESSAGE;
msg.setData(someResult);
messenger.send(Message.obtain());
}
Look into the docs for ExecutorService (not to be confused with Android Services) and the Executors package. There are a few examples there on how to use thread pools.
So wait, why do you need to use all these callbacks? Can't you just have each intent encode what needs to be done and then have your onHandleIntent execute different code based on the information of the intent. This is the way IntentService is intended to be used.
You shouldn't be doing any of the thread handling in the IntentSerivce. The IntentService is supposed to be handling all the threading code (and you should let it because it's probably highly optimized).