I have a question about accessing objects on the main thread from another thread. There seems to be a lot of information about it online with techniques to do that but everything I found applies to accessing Views on the UI thread. It may be that all those techniques also apply for objects other than View but I would just like to make sure.
For my concrete example I have a custom BluetoothDeviceConection class I wrote and contains functions like connect, closeConnection, write and so on. So functions for managing a connection to a specific BluetoothDevice which is passed as a parameter to BluetoothDeviceConection's constructor. On my main thread I create three BluetoothDeviceConection objects for three devices. Now I want to connect to all three devices.
My idea is to send the BluetoothDeviceConection object of a device to a new thread, let it connect to that device and write data to it, thereby manipulating / modifying / accessing the passed BluetoothDeviceConection object. To make this thread safe everyBluetoothDeviceConection object would be created with the volatile keyword.
Is that the correct way to go?
I am doing a similar thing with a TimerTask in which I call an "outside" function marked as synchronized and everything works fine.
Thank you in advance for all your help.
Cheers!
No, volatile does not guarantee thread safeness by itself. volatile only tells compiler this value can be changed from multiple threads so it doesn't apply optimizations based on static code analysis. If you want it to be thread-safe, you need to use synchronized as you said for TimerTask or other methods (locks, semaphores, mutexes...) to make sure only one thread is accessing it at any given time.
I also suggest that instead of passing the BluetoothDeviceConection as a parameter to other classes, you wrap this object inside another class and write thread-safe methods for manipulating it.
Same as with TimerTask your own class will work fine
Related
Will calling stage.act on a seperate thread within an infinite loop is a good idea?
Is there any pros and cons on this approach?
I've tried doing it,but im not sure if this will cause problem in the long run. it looks faster though.
From LibGDX documentation:
No class in libgdx is thread-safe unless explicitly marked as thread-safe in the class documentation.
You should never perform multi-threaded operations on anything that is
graphics or audio related, e.g. use scene2D components from multiple
threads.
From Stage api:
The Stage and its constituents (like Actors and Listeners) are not thread-safe and should only be updated and queried from a single thread (presumably the main render thread).
So how you can see, it's a bad idea.
We always write stage.act in render method and purpose of that we get time(dt) between 2 render method(Gdx.graphics.getDeltaTime()) call. You can write stage.act in your own loop. but for that you have to manage stop calling stage.act().
If you want to set same anim speed in every device then you should use
stage.act(Gdx.graphics.getDeltaTime()).
I'm using a recycler view in my app and would like to do some computation on a background thread, obtain a list of RealmObjects, and refresh my adapter to it.
As a bit of background, I have a non trivial sorting requirement, and the recycler view needs to display objects that result from queries on different tables(though they still produce the same object type). I don't want to do these potentially expensive queries on the main thread.
What is the best way to do this? AFAIK, I can
Get a list of ids(String) from the background thread, and do a query on the main thread. So I would do something like realm.where(ObjectA.class).in(listOfIds).findAll(). However, I don't think I have a guarantee that the order of the collection is the order of my listOfIds, which i have sorted in the background. I could then sort the realm collection manually.
Or, I can do a realm.copyFromRealm(listOfObjectA), assuming I have gotten a list of objects from my background thread. With this way it feels cleaner to me but i obviously lose the auto-refreshing functionality, not to mention that it will be memory-intensive. It seems that the expensive copying would take place on the main thread, which would undermine my efforts to move things into the background thread.
I was hoping there was a method that would allow me to transfer RealmResults or RealmList from one thread to the other. Does anyone have recommendations on how to do this?
findAllSortedAsync
I have a non trivial sorting requirement
If this sorting is based purely on your RealmObject fields, you can use RealmQuery.findAllSortedAsync(...) method, which will execute the query and sorting for you on a separate worker thread. This is the best option. If it's possible, you can also do sorting in two stages, one using findAllSortedAsync and second one on main thread on already obtained objects - possibly the second stage would not be as costly if the results are pre-sorted by realm.
and the recycler view needs to display objects that result from queries on different tables
You can look for a possibility to create a linking between these objects, for example if RealmObject A has a field b, you can sort A by fields of b also - this could fix your problem, and keep everything in one realm query.
Requery with sorted IDs (NO)
Get a list of ids(String) from the background thread, and do a query on the main thread...
You're right - there is no guarantee of the results being returned in the original ID list order, so this is not really an option.
copyFromRealm
Or, I can do a realm.copyFromRealm(listOfObjectA)...
That is correct, however you have to be aware of the limitiations and memory overhead using this method, namely:
you get a snapshot of the data and have to manually update the recycler with new snapshots
single change to an object conforming to your original query will trigger an update and, possibly, sorting all over again
It seems that the expensive copying would take place on the main thread, which would undermine my efforts to move things into the background thread.
Not really, if you perform copyFromRealm on thread A and pass the list to thread B, the hard copying of the values from realm will be executed by thread A, so it's fine.
You can not move "live" RealmObjects across threads, so the two options you've laid out are pretty much what you're left with.
If you do your query on the background thread and use copyFromRealm to create disconnected objects, sort them, and then pass those back to the main thread, that will all happen on the background thread, so you're fine there.
(Small note: if you display the data in a different format than it is in Realm, you could also map it to a class that's quicker to then populate your views from instead of using the Realm object in the UI, since you lost the sync features anyway.)
Otherwise, if you need them to be connected to Realm, I think you will have to do the ID list transfer and suffer the cost of sorting them on the main thread.
Use copyFromRealm method
In java:
MyRealmObject unManagedRealmObject= realmInstance.copyFromRealm(myRealmObject);
Well in kotlin, we can do it in a more better way:
var nonRealmObject: MyRealmObject?=null
set(value) { // here value is child of RealmObject
if (value!=null)
field = realmInstance.copyFromRealm(value) // converting RealmObject to unmanaged realm object
else
field=null
}
Now when you assign:
nonRealmObject = someRealmObject // set(value) method will be called and it will convert realm to unmanaged realm object
Note: realmInstance is an instance of Realm already created, if you create new reference make sure to close it when your work is done.
I am not fully understanding what the synchronization block is doing nor why it is necessary.
Can someone explain in a "synchronizing for dummies" kind of way?
In a book I am reading, the author tells me "The synchronization is necessary, since the members we manipulate within the
synchronized block could be manipulated in the onPause() method on the UI thread."
He creates an Object named stateChanged and instantiates it as a new object.
Then, in the synchronization block he uses the stateChanged object as the argument.
This whole thing is throwing me off and I do not like to move on until I have a pretty good understanding of what is going on.
The classic example is: Imagine you have two threads of operation, and both of them reference the same method:
public void addToGlobalVar(int y) {
int x = globalVar; //what if a thread stops right after this line?
x += y;
globalVar = y;
}
where globalVar is some other predefined number that this method can interact with and set. Lets say globalVar is 50.
Threads get computing time on a somewhat arbitrary basis, so you never fully know the precise nanosecond one stops and the other gets CPU time.
In this example, if you launched an AsyncTask in addition to the UI thread, and both at some point use addToGlobalVar(10), what can happen is that one thread might be interrupted at line 2 of that code block. If the other thread goes through while that one is sleeping, it will successfully set globalVar to 60. But when the other one wakes up, it still thinks x = 50, and its going to then set it to 60. So in essence you just made 50+10+10 = 60. Hopefully you can see how this becomes a problem.
You can fix this simple example by making the calculation atomic (skip declaring x, 1 line, all calcs done) or if the logic wasn't able to be condensed to 1 line, you make a block of code atomic by using synchronized.
The book to read is Java Concurrency in Practice.
You should really just segregate this idea from Android, although your code is going to be running on Dalvik this is a Java concept. Not an Android one.
The synchronized block takes an object as a parameter, any object, and when flow enters the body of the synchronized block, any other thread that runs in to a synchronized block with the same instance (object) as the parameter has to wait for the previous one to complete. That's a very basic description.
This is an entire sub-field of computer science and without serious study you will probably not understand it.
You have to fully understand it before you use it. It is standard android synchronization using object-oriented monitors. You have to understand it to write multi-threaded programs, however it is somehow dated (better use java.util.concurrent for anything thread/synchronisation related instead).
Anyhow - you need to know what it is about - read the related java tutorial part:
http://download.oracle.com/javase/tutorial/essential/concurrency/sync.html
i am new in android and java ... i am reading from couples of day about android parceling tutorial for transfer data or variables values from one activity to other or one class to other ... but i am not so understood about that.
can u tell me that is it necessary to use Parcelable for this purpose because same task can also be perform using static key word for variables as string,int or array type then why parcelable pls explain in detail ..
thanks for explanation in advance please provide comparison with example
While technically both approaches will work, there are a couple of flaws.
The first is that the static variable is static. If you have two instances of the same activity, they will both reference the same static object. This is probably not what you want.
Secondly, it's considered bad practice to access global variables. It makes it difficult to see what is going on, is difficult to test and you someone (another class) can modify your data. This creates some horrendous bugs.
By passing the data via a Parcelable object it is very clear what you are doing and you avoid both of these problems.
Note that this advice is not specific to Android, rather to Java and programming in general.
Static references never get garbage collected so you end up creating something called a memory leak.
You are keeping an object in memory that you don't need and it can't be freed up.
If you instantiate enough objects like this you will get an out of memory (oom) exception which will cause the app to crash.
I have a simple query returning a Cursor, and then I walk the cursor and create objects that I throw in an ArrayList, like this:
List<Element> myElements = new ArrayList<Element>();
Cursor c = db.query(...);
c.moveToFirst();
while (c != null && !c.isAfterLast()) {
myElements.add(new Element(cursor.getString(0).........)); <-- CREATING THE ELEMENT
c.moveToNext();
}
...
You get the idea.
The problem is that I need to run 4 queries like this hitting different tables, etc, but they all return the same Element object in the end (after walking the cursor).
Being a good Android citizen I created a class extending AsyncTask to avoid hogging the UI Thread. Also, I want to run the 4 queries in 4 threads to speed things up.
The question:
in my onPostExecute(Cursor c), I'm running the logic marked as "CREATING THE ELEMENT" above. If I run 4 threads with 4 queries and all modifying the List, will I have thread conflicts touching the same variable from them? How do I prevent that? Do I gain anything by threading this if the list I need to modify is synchronized? I mean, the threads will have to wait in line anyway, I might as well write the 4 queries and run them sequentially... or not?
I understand I want to keep this out of the UI Thread. The question is if I want to create 4 threads (each running in an AsyncTask) or just ONE AsyncTask that runs the 4 queries sequentially.
Thanks!
Llappall
will I have thread conflicts touching the same variable from them?
You will certainly have race conditions - if you are fine with it then no issues.
How do I prevent that? Do I gain anything by threading this if the list I need to modify is synchronized?
I don't think so.
I mean, the threads will have to wait in line anyway, I might as well write the 4 queries and run them sequentially... or not?
The question is if I want to create 4 threads (each running in an AsyncTask) or just ONE AsyncTask that runs the 4 queries sequentially.
I would run all the 4 queries in one AsyncTask, creating 4 AsyncTasks would be a lot to do and maintain.
Vector, as opposed to ArrayList, is synchronized and thread safe, so I would suggest to use it instead.
http://download.oracle.com/javase/6/docs/api/java/util/Vector.html
Another alternative would be to create a new List per thread and then use Collections.addAll() to incorporate the elements to the original list.
To answer the question whether you would gain anything by starting multiple threads, probably the answer will depend on how expensive are the queries you are doing. Starting a new thread has an intrinsic overhead, so you want to make sure that the query you are starting is worth the cost.