In an android project of mine I'm using the jamod library for Modbus communication and it works alright. Except when the network connection isn't available then my asynchronous task will be stuck on transaction.execute for seconds. I would like to cancel it after a given timeout. I tried to implement a handler for this to cancel the asynchronous task:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (task.getStatus() == AsyncTask.Status.RUNNING
|| task.getStatus() == AsyncTask.Status.PENDING) {
task.cancel(true);
}
}
}, WRITE_TASK_TIMOUT);
But this approach won't work. I looked into the library and saw that the ModbusTCPTransaction.execute() method uses synchronized().
Does this mean i have no chance to cancel this method after x seconds?
You could try to use Android class Future. It has method to set the timeout period of the thread execution.
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
future.get(5, TimeUnit.SECONDS);
static class Task implements Callable<String> {
#Override
public String call() throws Exception {
//ModbusTCPTransaction.execute()
return null;
}
}
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;
}
So I have this method called PredictionEngine(int) that I want to run a certain number of time with a certain time-delay between each run. The method goes like this:
private void PredictionEngine(int delay) throws Exception {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
enableStrictMode();
String val = null;
try {
if (tHighPass == 0 && tLowPass == 0 && tKalman == 1) {
//Magic
} else {
//Magic
}
} catch (Exception e) {
e.printStackTrace();
}
enableStrictMode();
new DropboxTask(side_output, "Result", val).execute();
}
}, delay);
}
As obvious, I am running a network operation in the main thread as this is a research app and no client is ever going to use it.
I want this whole function to run for say a 100 times with a certain delay, say 2 seconds. The initial thought was to do this:
for(loop 100 times){
PredictionEngine(int)
Thread.sleep(2000); //sorry for StackOverflow programming.
}
However I don't want to block the main thread as I am reading some sensor data there. Any ideas for the same would be very helpful!
Thanks.
The best way to solve this is by using rxJava library, because it allow to create, modify and consume streams of events. You can implement everything in a few lines of code and modify it so operatioin will be performed in background as well.
Observable.interval(1, TimeUnit.SECONDS)
.take(100)
// switch execution into main thread
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(t -> {
doSomethingOnMainThread();
});
On the other hand, there is another solution- you can use Handler, which is usually bein used for thread communication. It has method .postDelayed() allowing you to postpone execution of task. Handler can be conveniently used along with HandlerThread. But, rxJava is more convenient and simple way to solve your problem.
While creating your Handler, you can provide a looper as one of the constructors parameters that is based on different thread then the main thread:
HandlerThread thread = new HandlerThread("Thread name", android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
Looper looper = thread.getLooper();
Handler handler = new MyHandler(looper);
Messages received by MyHandler will be processed on a separated thread, leaving the UI thread clear from interferences.
To loop on the task periodically, use something like:
for (int i=0; i<100; i++){
handler.postDelayed(new Runnable(){
...
...
...
}, i*delay);
}
This way, in case you decide that the periodic tasks need to be canceled, you will always be able to invoke:
handler.removeCallbacksAndMessages(null);
I tried to solve the issue as follows without blocking the main Thread
I created the worker thread for looping and still running the predictionEngine() on main thread
MyThread t = new MyThread(2000, 3000); // delay and sleep
t.startExecution();
Worker thread class looks as follows
class MyThread extends Thread{
private int delay;
long sleep;
MyThread(int delay, long sleep){
this.delay = delay;
this.sleep = sleep;
}
#Override
public void run() {
for(int i = 0; i < 100; i++){
try {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
predictEngine(delay);
}
});
Log.i("Mtali","About to pause loop before next predict");
sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void startExecution(){
start();
}
}
Hop this helps!
I have a problem with unit tests in Android.
My object MyObject has a method start() like this :
public void start() {
final Handler onStartHandler = new Handler();
new Thread() {
#Override
public void run() {
super.run();
onStartHandler.post(new Runnable() {
#Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
}.start();
}
And I want to test that onStart() is called.
So I tried something like that :
public void testOnStartIsCalled() {
assertFalse("onStart() should not be called", mMyObject.isRunning());
mMyObject.start();
assertTrue("onStart() should be called", mMyObject.isRunning());
mMyObject.stop();
assertFalse("onStop() should be called", mMyObject.isRunning());
}
But it doesn't work, I guess it's because it's in a Handler and a new Thread.
My test class extends AndroidTestCase.
What should I do ? What is the best practice for this case ?
Regards.
When I deal with testing some multi-threaded code I try to let the program take as much of its natural flow as possible. Additionally, I avoid the use of sleep statements since you don't get any guarantees that the sleep interval you've chosen is enough to allow the subject of your test to finish what it's doing; you often end up having to choose sleep intervals that are too large and it forces a much slower execution of your test cases.
I would recommend that you try to add some code into the class you're testing, in this case MyObject, which call a listener whenever something happens. It seems that you already have callback methods for onStart() and onStop()(if those are events/callbacks), so those should be getting invoked and you should use them to control the flow of your test. When you get an onStart() event, you should then call stop() and wait for an onStop() event.
Update
First and foremost, you have redundant code:
public void start() {
final Handler onStartHandler = new Handler();
new Thread() {
#Override
public void run() {
super.run();
onStartHandler.post(new Runnable() {
#Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
}.start();
}
Either start a new thread to call onStart() or schedule the runnable on the Handler's thread queue.
Version 1- remove the handler and just let the code be executed in a new thread:
public void start() {
new Thread() {
#Override
public void run() {
super.run();
mIsRunning = true;
onStart();
}
}.start();
}
Version 2- only use the handler to asynchronously execute the callback:
public void start() {
final Handler onStartHandler = new Handler();
onStartHandler.post(new Runnable() {
#Override
public void run() {
mIsRunning = true;
onStart();
}
});
}
And second: I noticed is that if you don't have a Looper, then whatever you post with the Handler will be ignored (thus it will never be called). For more information on the Looper-Handler pattern see the article: Android Guts: Intro to Loopers and Handlers. The Looper and the Handler are supposed to be attached to the same thread (usually the main thread). Additionally, if you're creating the Handler on a separate thread as your Looper, then you'll run into the same problem: anything you post with the Handler will be ignored.
Here are a few more good questions and articles on loopers and handlers:
Just do IT: looper and handler in android
Handler-Looper implementation in Android
The relationships between Looper, Handler and MessageQueue is shown below:
The problem here is that you are calling onStart() which invokes a new thread, and then immediately ask if it is started. There is startup time for the new thread and while that is happening, your test is asking if it is started -- it's not YET.
I bet if you waited by using Thread.sleep(), or a loop, you'd find it is started "eventually".
What is it you're actually trying to test?
If you need the new thread, you might want to read up on threads, synchronize, etc.
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
I have a Service that launches a Thread and a Runnable like so.
t = new Thread(new Runnable() {
public void run() {
doSomething();
}
});
t.start();
The reason for the thread is to perform an Async task doSomething(). For now lets not worry about the other class AsyncTask. I have tried it and it does not work for my case. Edit: I can't use AsyncTask because it is meant for the UI thread only. This piece of code has to operate inside a Service, so nope, no AsyncTask :(
doSomething() contains some external libs so the issue I am having is that it can potentially be hung at one of the commands, without return any value (hence no error checking can even be done)
To work around this, I will want to, at some point of time, destroy the Service.
stopService(new Intent("net.MyService.intent));
This works fine and is easily verified on the phone. However, the Thread which was created above will continue to run even when the Service that spawned it is destroyed.
I am thus looking for the correct commands to insert in the Service's onDestroy() which will clean up the Thread for me.
t.destroy();
t.stop();
are both depreciated and cause application crashes.
I took this code from somewhere
#Override
public void onDestroy() {
Thread th = t;
t = null;
th.interrupt();
super.onDestroy();
}
but it still does not work, the thread continues to run. Any help guys?
The thread destroy and stop methods are inherently deadlock prone and not safe. Their existence also gives the illusion that there might be some way of halting another thread immediately when something else tells it to.
I understand your thinking, from your point of view their is one main thread, and when this thread hasn't received a response from it's worker thread in a while you'd like to kill it and restart it, without caring what it's up to. But the reason those methods are deprecated is you should care what the thread is up to. A lot.
What if the thread has a lock around a variable you need to use later? What if a thread has a file handle open? In all these cases, and many more, simply stopping the thread at it's current operation would leave things in mess -- quite likely your application would just crash further down the line.
So in order for a thread to be interruptible or cancel-able or stoppable, it has to manage this itself. If a thread or operation provides no way for itself to be interrupted, then you cannot interrupt it - it is assumed to do so would be unsafe.
If you runnable is literally
public void run() {
doSomething();
}
then there is no way to interrupt it. One would hope that if doSomething were a long operation that there might be a way to either interact with it incrementally with something like
public void run() {
while (running) {
MyParser.parseNext();
}
}
or to be able to pass in a variable by reference which indicates whether the thread is interrupted or not, and hopefully the method would interrupt itself at suitable location.
Remember a blocking operation is blocking. There is no way to get around that, you cannot cancel it part way through.
Alternative answer
Use the following code:
MyThread thread; // class field
Create and start the thread as you do it right now.
thread = new MyThread();
thread.start();
When the service is destroyed, "signal" the thread to quit
public void onDestroy() {
// Stop the thread
thread.abort = true;
thread.interrupt();
}
Here is thread implementation
//another class or maybe an inner class
class MyThread extends Thread {
syncronized boolean abort = false;
//ugly, I know
public void run() {
try {
if(!abort) doA();
if(!abort) doB();
if(!abort) doC();
if(!abort) doD();
} catch (InterruptedException ex) {
Log.w("tag", "Interrupted!");
}
}
}
You might want to read the following:
How do you kill a thread in Java?
Thread Primitive Deprecation as already pointed by Claszen
http://www.devx.com/tips/Tip/31728 - based my code from here, but there are some issues with the code!
I think that you could rely on catching the exception and not check abort but I decided to keep it that way.
UPDATE
I've seen this sample in codeguru:
public class Worker implements Runnable {
private String result;
public run() {
result = blockingMethodCall();
}
public String getResult() {
return result;
}
}
public class MainProgram {
public void mainMethod() {
...
Worker worker = new Worker();
Thread thread = new Thread(worker);
thread.start();
// Returns when finished executing, or after maximum TIME_OUT time
thread.join(TIME_OUT);
if (thread.isAlive()) {
// If the thread is still alive, it's still blocking on the methodcall, try stopping it
thread.interrupt();
return null;
} else {
// The thread is finished, get the result
return worker.getResult();
}
}
}
Did you check the Java Thread Primitive Deprecation Documentation which is referenced in the Thread API JavaDoc. You will find some hints to handle your problem.
why don't you use an AsyncTask?
A task can be cancelled at any time by
invoking cancel(boolean). Invoking
this method will cause subsequent
calls to isCancelled() to return true.
After invoking this method,
onCancelled(Object), instead of
onPostExecute(Object) will be invoked
after doInBackground(Object[])
returns. To ensure that a task is
cancelled as quickly as possible, you
should always check the return value
of isCancelled() periodically from
doInBackground(Object[]), if possible
(inside a loop for instance.)
I like to take the following approach:
class MyHandler extends Handler {
final Semaphore stopEvent = new Semaphore(0);
#Override
public void handleMessage(Message msg) {
try {
while (!stopEvent.tryAcquire(0, TimeUnit.SECONDS)) {
doSomething();
if (stopEvent.tryAcquire(SLEEP_TIME, TimeUnit.MILLISECONDS)) {
break;
}
}
} catch (InterruptedException ignored) {
}
stopSelf();
}
}
On service onDestroy just release the stopEvent:
#Override
public void onDestroy() {
myHandler.stopEvent.release();
myHandler = null;
super.onDestroy();
}
Better to use global variable stopThread, stop thread once variable changed to true.
btnStop.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0){
stopThread = true;
}
});
public void run() {
while (!stopThread) {
//do something
}
}
I think the best way to create and communicate with another thread is to use an AsyncTask. Heres an example of one:
public class Task extends AsyncTask<Void, Void, Void> {
private static final String TAG = "Task";
private boolean mPaused;
private Runnable mRunnable;
public Task(Runnable runnable) {
mRunnable = runnable;
play();
}
#Override
protected Void doInBackground(Void... params) {
while (!isCancelled()) {
if (!mPaused) {
mRunnable.run();
sleep();
}
}
return null;
}
private void sleep() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w(TAG, e.getMessage());
}
}
public void play() {
mPaused = false;
}
public void pause() {
mPaused = true;
}
public void stop() {
pause();
cancel(true);
}
public boolean isPaused() {
return mPaused;
}
}
You can now easily use this class, and start the thread by writing:
Task task = new Task(myRunnable);
task.execute((Void) null);
Along with this you can easily pause or stop the thread from looping:
Example of pausing and playing the thread:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (task.isPaused()) {
task.play();
} else {
task.pause();
}
}
});
Example of stopping and starting the thread:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (task.isCancelled()) {
task = new Task(myRunnable);
task.execute((Void) null);
} else {
task.stop();
}
}
});
I am developing on Android but the question might be just as valid on any other Java platform.
I have developed a multi-threaded app. Lets say I have a first class that needs to do a time-intensive task, thus this work is done in another Thread.
When it's done that same Thread will return the time-intensive task result to another (3rd) class.
This last class will do something and return it's result to the first-starting class.
I have noticed though that the first class will be waiting the whole time, maybe because this is some kind of loop ?
Also I'd like the Thread-class to stop itself, as in when it has passed it's result to the third class it should simply stop. The third class has to do it's work without being "encapsulated" in the second class (the Thread one).
Anyone knows how to accomplish this ?
right now the experience is that the first one seems to be waiting (hanging) till the second and the third one are done :(
If you want to use threads rather than an AsyncTask you could do something like this:
private static final int STEP_ONE_COMPLETE = 0;
private static final int STEP_TWO_COMPLETE = 1;
...
private doBackgroundUpdate1(){
Thread backgroundThread = new Thread() {
#Override
public void run() {
// do first step
// finished first step
Message msg = Message.obtain();
msg.what = STEP_ONE_COMPLETE;
handler.sendMessage(msg);
}
}
backgroundThread.start();
}
private doBackgroundUpdate2(){
Thread backgroundThread = new Thread() {
#Override
public void run() {
// do second step
// finished second step
Message msg = Message.obtain();
msg.what = STEP_TWO_COMPLETE;
handler.sendMessage(msg);
}
}
backgroundThread.start();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch(msg.what){
case STEP_ONE_COMPLETE:
doBackgroundUpdate2();
break;
case STEP_TWO_COMPLETE:
// do final steps;
break;
}
}
}
You would kick it off by calling doBackgroundUpdate1(), when this is complete it sends a message to the handler which kicks off doBackgroundUpdate2() etc.
Tiger ,
TiGer wrote:
When it's done that same Thread will
return the time-intensive task result
to another (3rd) class
Since thread runs asynchronously so your non-thread class can't be synced with your thread
Though to perform some action on an Activity you need an AsyncTask not A Thread
TiGer wrote:
maybe because this is some kind of
loop ?
Tiger do read more about Threads and concurrency
So the only answer I have for you now is ASYNCTASK
EDIT:
Also I'd like the Thread-class to stop
itself
Read this post's how-do-you-kill-a-thread-in-java
In ordinary Java, you would do this:
class MyTask implements Runnable {
void run() {
for (int i = 0; i < Integer.MAX; i++) {
if (i = Integer.MAX -1) {
System.out.println("done");
}
}
}
}
class MyMain {
public static void main(String[] argv) {
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new MyTask());
t.start();
}
System.out.println("bye");
}
}
... that kicks off 10 threads. Notice that if you accidentally invoke t.run() instead of t.start(), your runnable executes in the main thread. Probably you'll see 'bye' printed before 10 'done'. Notice that the threads 'stop' when the the run() method of the Runnable you gave to them finishes.
I hope that helps you get your head around what it is you've got to co-ordinate.
The tricky part with concurrency is getting threads to communicate with each other or share access to objects.
I believe Android provides some mechanism for this in the form of the Handler which is described in the developer guide under designing for responsiveness.
An excellent book on the subject of concurrency in Java is Java Concurency in Practice.
if you want use AsyncTask rather then thread in android
I have resolve it using ASyncTask and Handler in Android the aim is that one task is execute after compilation of one task hear is code that show First load animation on view after compilation of that process it will goes on another page
class gotoparent extends AsyncTask<String,String,String>
{
#Override
protected String doInBackground(String... params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Animation animation= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotete);
lin2.startAnimation(animation);
}
});
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i=new Intent(getApplicationContext(),ParentsCornor.class);
startActivity(i);
}
}, 1200);
}
}