Android , thread usage - android

My program is sending data to web server when accelerometer datas exceed the threshold which determined by me. So , I used thread mechanism for sending operation :
if( threshold is exceeded )
thread_send .start();
But this usage cause "Thread Already Used" error. So I used a method that I think is bad is below and it works :
if( threshold is exceeded ) {
thread_send = new Thread(this);
send_thread.start();
}
New thread is created at every turn. Does that usage cause negative results? (For example, memory problem or performance problem etc.)
What are your suggestions?
Editted :
My program should send data to web server very often. The most important thing is working correctly.So slow working is allowable , as long as the program can't stop suddenly..
I used ExecutorService in line with your suggestions :
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
........
if( threshold is exceeded ) {
threadExecutor.execute(this);
}
But errors occured : RecejtedExecutionException..
What can I do ?

The second code looks correct, though it may slow it down if too many threads are running in parallel. Depending on the application, it might be appropriate to have threads run one-at-a-time in a queue, using Executors.newSingleThreadExecutor.

One idea is creating a singleton like service that runs the thread, that way if one isn't running, then it starts one, otherwise it ignores it.
If you want multiple running at the same time, what you have is correct. Remember a thread can only be ran once per new Thread()

Related

Activity not updating in tight loop

I have a situation where I want to update an Activity's text fields as data comes in. The update only occurs when the simulation is completed, not while it is running (takes maybe 2 seconds to run).
Here is the code I have:
...
private var totalLoops = 0
private val updateDisplayTask = Runnable {
totalLoopsTV.text = totalLoops.toString()
totalEmailsSentTV.text = totalEmailsSent.toString()
totalPushesSentTV.text = totalPushesSent.toString()
private fun mainLoopFunction(currentTime: Long) {
...
totalLoops++
if(totalLoops % 20 == 0 || onDeckList.size == 0) {
Timber.w("UPDATING UI")
runOnUiThread(updateDisplayTask)
//handler.post(updateDisplayTask)
}
} //end of main loop
I've tried both runOnUiThread and handler/post as well as a few other things using Kotlin Coroutines, but nothing so far has worked. Can you see what I'm doing wrong here please? I see the logs of UPDATING UI so I know that the updates do get sent and I do see the last update (the only one I see) at the end.
Is this running on another thread, and then you run updateDisplayTask on the main thread? If you're updating totalLoops, totalEmailsSent and totalPushesSent on one thread (this worker thread) and reading them on another (main thread) then because of the way concurrency works, you might not actually see the new values on the main thread.
There are a few ways to manage synchronizing them, but if you're only writing the values on one thread (and you're not massively concerned about the possibility of some of the values changing partway through reading them, so they don't all match up) you can just use the #Volatile annotation on those variables to make them update across threads (works like the volatile keyword in Java).
If you care about atomic updates (everything changing together, can't read or write while something is in the middle of reading or writing them) you'll have to look into some kind of locking, like using synchronized methods and blocks. It's kind of a major (important!) subject, here's a post on it:
https://proandroiddev.com/synchronization-and-thread-safety-techniques-in-java-and-kotlin-f63506370e6d

Xamarin Android correct Asynchronous way

i am new on xamarin android apps.I want to build an app and i have read that connections with database or the execution of queries should happen asynchronously from the main thread otherwise the UIthread will may collapse.I have found 2 ways to do that:
First way:
WebClient client = new WebClient();
Uri uri = new Uri("http://192.168.2.8/CreateUsername.php");
NameValueCollection parameters = new NameValueCollection();
parameters.Add("Name", txtname.text);
client.UploadValuesCompleted += Client_UploadValuesCompleted;
client.UploadValuesAsync(uri,parameters); ---> is this gonna create a new thread and run asynchronously???
(here i found the first way: https://www.youtube.com/watch?v=jF3D__ibrx8 )
SecondWay:
https://developer.xamarin.com/recipes/android/web_services/consuming_services/call_a_rest_web_service/
Both ways are correct?both of ways are gonna create a new thread and run asynchronously?Thanks!!!!
Both examples are ok but I'd usually trust the official documentation by Xamarin first. What might confuse you with the first example is the lack of await keyword when calling the UploadValuesAsync method. Here's what actually happens:
Call to UploadValuesAsync is made from the UI thread.
UI thread blocks until the method returns because it's running synchronously.
However, the method returns very quickly because it launches the upload process asynchronously on another thread internally and doesn't wait for the process to complete.
When the whole upload process is finished, Client_UploadValuesCompleted will be called.
As you can see on the WebClient.UploadValuesAsync page on MSDN, it states that:
These methods do not block the calling thread.
Also, when looking at the source code for UploadValuesAsync, you'll notice the following attribute defined on top:
[HostProtection(ExternalThreading=true)]
which means the following:
Code that exposes external threading creates or manipulates threads other than its own, which might be harmful to the host.
To sum it up, the upload process is handled on another background thread but otherwise, your code will run synchronously. There's a bit more asynchronicity going on in Xamarin's sample.

ExecutorService one threaded threadpool is blocking the queue if too many requests are executed

I am using a threadpool with only one thread to execute some network tasks (They need to be executed sequentially)through a viewholder in a RecyclerView in Android. It is working, if I am scrolling slow. But if I am scrolling fast, too many tasks will be pushed to the queue, which I have discovered through debugging, is blocking the queue entirely.
I have simplified the code (much) where I am using the one threaded threadpool:
if (executorService == null) {
executorService = Executors.newFixedThreadPool(1);
}
executorService.execute(new Runnable() {
#Override
public void run() {
RessourceService.getCoverPage(url, callback);
while (waiting) {}
}
});
So what is the alternatives, if I want to execute network tasks sequentially without getting a blocked queue?
Have you tried using newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor()
Creates an Executor that uses a single worker thread operating off an
unbounded queue.
(Note however that if this single thread terminates
due to a failure during execution prior to shutdown, a new one will
take its place if needed to execute subsequent tasks.)
Tasks are guaranteed to execute sequentially, and no more than one task will be
active at any given time. Unlike the otherwise equivalent
newFixedThreadPool(1) the returned executor is guaranteed not to be
reconfigurable to use additional threads.
(Posted answer on behalf of the question author).
The problem was somewhere else in my code and not in that posted in the question. As described in my question, I am executing the requests through a viewholder of a recyclerview. When scrolling fast, the images are not loaded. I found out that the problem was occurring when an item was out of sight in the recyclerview. The reason for this, was that the request was locked due to my "waiting" variable being true. I could solve it by making it static and setting it to false right before each request and thereby stopping the request in progress in another viewholder.
Nevertheless, the suggesting by #Jessie Brian Revil on using newSingleThreadExecutor, makes perfectly sense. Not a direct solution to my problem, but a reasonable solution for the code above (therefore accept).

Updates from C thread leads to Choreographer skipping frames

I have a C thread that is making requests and receiving updates from a server. The updates are sent to Java through JNI calls. My problem happens when I'm receiving a player's inventory which can contain up to 100 items (100 responses from the server, I cannot modify this part). Sometimes the problem happens, sometimes not but the bigger the inventory is, the more often I have this issue.
I don't get any exception in the logcat except the following message :
06-10 10:09:46.085: I/Choreographer(23815): Skipped 87 frames! The application may be doing too much work on its main thread.
And then my app closes. I also need to say that even when I comment the lines where I update the UI with runOnUiThread the app crash.
I tried to check if I'm on the UI Thread when I return to Java with JNI but Looper.myLooper() == Looper.getMainLooper() return false.
Anyone experienced the same problem ? Are the C threads related to the main thread somehow ? Thanks
EDIT
When I receive an update from the server the following calls are made :
From a Java Thread (not the UI thread) : call a C function named notifyAll
From notifyAll call a C function named update which will call its equivalent in Java (see code below)
void UpdateListenerWrapper::update(Update& u) {
// Retrieve the current JNIEnv* with the cached JVM
int status;
JNIEnv* env;
bool isAttached = false;
status = gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2);
if(status < 0) {
__android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to get JNI environment");
status = gCachedJVM->AttachCurrentThread(&env, NULL);
if(status < 0) {
__android_log_print(ANDROID_LOG_ERROR, "UpdateListenerWrapper", "Failed to attach current thread");
return;
}
isAttached = true;
}
jmethodID update = env->GetMethodID(gClazzUpdateListenerWrapper, "update", "(J)V"); // J stands for Java long type
// Call Java method update from jUpdateListener object
env->CallVoidMethod(jUpdateListener, update, (jlong)(intptr_t)&u); // Pointer as agument, we'll build the Update object in Java
if (isAttached) {
gCachedJVM->DetachCurrentThread();
}
}
I think the problem is at this line gCachedJVM->GetEnv((void **) &env, JNI_VERSION_1_2); and maybe GetEnv return a pointer for the UI thread. Could that be the problem ? How can I fix this ?
The app crash is unrelated to the Choreographer complaints. Those are just a warning that indicates the animation is being starved.
You really want to be viewing the logcat output in a mode that shows thread IDs. I recommend adb logcat -v threadtime from the command line. If you put a log message at the start of your server interaction you can easily see if it's running on the UI thread (thread ID and process ID are the same -- not guaranteed by the system, but reliably true in apps).
Never do network or database I/O on the main thread. If it takes too long, the system gets bored and decides that your app is not responding.
Calling into native code through JNI does not switch you to a different thread. There are not C threads and Java threads, just threads, which can call in and out of code written in C and Java.
Re: question updates...
GetEnv always returns a pointer to data for the current thread. Also, CallVoidMethod always happens in the current thread; even if you passed in the wrong JNIEnv it wouldn't "jump" threads.
The GetMethodID call can be expensive in a class with a lot of methods, so you should try to cache that at the same point where gClassUpdateListenerWrapper is set up. Attaching and detaching the thread from the VM can also be expensive and is something best avoided -- and if you're calling here from a Java method, then by definition it's attached already. I would guess that isAttached is never being set.
That doesn't really explain why the Choreographer is starving though. I think you still need to add a log message to C update() and use logcat -v threadtime to get a sense for what is happening on which threads, and use traceview to see where the time is going.
I found the solution to my problem but it's kind of specific to my app. In the update function (Java side), I had a case which had no break and each updates were triggering new network calls (not in the UI thread). Nasty to find but thanks for your time and your answers, you helped me to solve this :)

How to avoide android ANR

I have one library which is linked to my Android application, I am calling some functions of that lib from my android Activity and those function calls are time taking (4-5 seconds).
I can not call this functions in separate thread (using AsyncTaks, Threads) because of the library limitations.
When i call these function and when these function are in process at the same time my UI does not respond to user activities and to avoid that i am displaying processing screen and if in-between user performs any key actions then i get ANR error.
How can i avoid this ANR or there is no way i can avoid it other that putting time taking process in separate thread?
Thanks.
better read this article and watch google IO videos (like this one and this one) .
if you don't have time for this , simply remember this simple rule:
long operations (like internet operations , DB operations , IO operations , and anything that could simply take longer than 5 seconds ) could cause ANR if they occur on the UI thread.
for updating the UI , you must use the UI thread . if you need to do it after/during the long operation , use classes such as : Handler , AsyncTask , View.post , Activity.runOnUiThread .
Who wrote the library and what is it? The only reason I can think of as to why it would throw an exception is that it is trying to update the UI from the thread that you call it on. If the library methods take 4-5 seconds to compete then they should provide you with a callback mechanism that you can update your UI on the UI thread.
new Thread("Slow native process") {
public void run() {
// call your "time taking process", passing in the callback (you could implement in the outer class and pass "this"...)
callNativeMethod( args, new YourCallbackInterface() {
public void onResult( String response ) {
activity.runOnUiThread( new Runnable() {
// update UI
});
}
});
}
}.start();

Categories

Resources