How does Thread() work in Kotlin? - android

I wanted to execute a task inside a thread and wrote the following code:
Thread().run {
Log.i("TEST", "in thread")
Thread.sleep(5000);
transactionStatus = ApiFactory.getInstance().transactionService.abortTransaction()
synchronized(TestTransactionPayAbort.lock) {
TestTransactionPayAbort.lock.notify()
}
}
Log.i("TEST", "main")
synchronized(TestTransactionPayAbort.lock) {
TestTransactionPayAbort.lock.wait()
}
According to the debugger, before executing Thread().run{}, I'm inside thread 4.
After executing Thread.sleep(), the debugger tells me that thread 4 is sleeping whereas I was expecting to see that thread 5 is sleeping. About the Log(): I see immediately in thread and main 5 seconds later.
What is my mistake here?

I think the syntax you’re looking for is:
Thread {
// your execution code
}.start()
Also read this answer for further information.

Related

One hour break between two lines of code in android

I am building an android application and I want an hour gap between two lines of code,
I use thread.sleep() method with 1800000 seconds but it makes my application irresponsive and closed the execution.
Any suggestions or help would be beneficial for me.
As #GaneshPokale suggested above, WorkManager is the best solution for your case.
Don't stop Main thread(=UI thread): Sleeping in the Main thread will stop your entire app, and it will lead you to ANR, which will make your app killed if your app is stopped more than 5 sec.
In this case, you need to create another thread. WorkManager is one of the solutions for such cases, which need to wait a long time. You can also use AlarmManager or some other ways.
Try running the code on a different thread:
class MyThread implements Runnable {
public void run() {
try {
Thread.sleep(1800000000);
} catch (InterruptedException err) {
//handle interruption
}
System.out.print("world!");
}
}
class Main {
public static void main(String[] args) {
System.out.print("Hello ");
Thread t = new Thread(new MyThread());
t.start();
}
}
This will allow the main thread to continue running tasks while the second one is waiting in the background.

ExecutorService can not reuse its thread

I have the following task:
void task()
{
Looper.preapre();
handler = new Handler();
runnable = new Runnable()
{
if(notDone)
{
doSth();
handler.postDelay(runnable,timeInterval);
}
else
{
handler.removeCallBacks(runnable);
returnResult(); / the task is done and return some results
}
}
handler.post(runnable);
Looper.loop();
}
I use ExecutorService with single worker thread to run this task, the 1st time it runs just fine but the 2nd time the task is never be executed because the worker thread is still running the 1st task although i call removeCallBacks. Does anyone know where the problem is? Thanks in advance.
PS: I have try Looper.quit() but it kills the thread so the executor can not run the task on the dead thread.
After doing a research, i found that when a looper is attached to a thread, it will keep the thread active all the time even the thread is idle, so the ExecutorService can not get back the idle thread

wakelock inside a running thread Android

I have this simple question:
In a service i need to run 2 more threads independent from each other, and i need a wakelock to let them be executed. I give you an example:
wl.aquire();
if (true) {
mExecutorService.execute(thread1);
}
if (true) {
mExecutorService.execute(thread2);
}
wl.release();
So, in this case, the wake lock will be released once the 2 threads have started or does it wait for them to finish?
If not, i need the wakelock to stay up while they're running, and release it only when the last thread has finished. How can i do that? Do i have to acquire new wakelocks inside the thread's body?
Thank you
According to the Executor execute() documentation: "Executes the given command at some time in the future. The command may execute in a new thread, in a pooled thread, or in the calling thread, at the discretion of the Executor implementation."
So it depends on which concrete Executor you are using.
I think you are supposed to use submit() to give a new job to an Executor.
If you stick with the Executor, calling get() on the Future returned by submit() will block until the result is available.
So you could call:
Future<Result> result_1 = mExecutorService.execute(Runnable1);
Future<Result> result_2 = mExecutorService.execute(Runnable2);
result_1.get();
result_2.get();
Alternatively, you could start two threads and wait for them to finish:
Thread t1 = new Thread(Runnable1);
Thread t2 = new Thread(Runnable2);
t1.start();
t2.start();
t1.join();
t2.join();
Hope this helps.
Assuming you are running this code from AsyncTask or background thread. You can call [Thread.join()] on all the threads before the call to wl.release();
check out this link for join() detail
EDIT1: on executor you can also use awaitTermination() with long wait value to wait for it to finish all the tasks. Following code is from the official java doc:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
See http://developer.android.com/reference/android/os/PowerManager.WakeLock.html -- the correct way would be to acquire the wakelocks inside the two threads you are running. Given your example code, you will need a member variable inside thread1 and thread2 to store the wakelock, and some way to pass the wakelock in, perhaps like this:
thread1.setWakelock(wl);
thread2.setWakelock(wl);
class Thread implements Runnable {
PowerManager.Wakelock mWakelock;
void setWakelock(PowerManager.Wakelock wl) {
mWakelock = wl;
}
}
Then inside thread1 and thread2, you will need:
run() {
mWakelock.acquire();
... your existing code here ...
mWakelock.release();
}
Note that this will work since wake locks are reference counted by default; see PowerManager.WakeLock.setReferenceCounted().
Waiting for the threads to finish using thread.join() is wrong; it will block the UI thread and you will get an ANR, as you found out.

Android: got CalledFromWrongThreadException in onPostExecute() - How could it be?

I have an app in production for a few weeks, using ACRA, and I had zero errors until one strange error reported today.
I've got:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
coming from this method in the stack trace (retraced):
at my.app.CountdownFragment$1.void onPostExecute(java.lang.Object)(SourceFile:1)
And this is the relevant source snippet:
private void addInstructionsIfNeeded() {
if (S.sDisplayAssist) {
new AsyncTask<String, Void, String>() {
#Override
protected String doInBackground(String... params) {
return null;
}
/*
* runs on the ui thread
*/
protected void onPostExecute(String result) {
Activity a = getActivity();
if (S.sHelpEnabled && a != null) {
in = new InstructionsView(a.getApplicationContext());
RelativeLayout mv = (RelativeLayout) a
.findViewById(R.id.main_place);
mv.addView(in.prepareView());
}
};
}.execute("");
}
}
Where addInstructionsIfNeeded() is called from a handler dispatched message (the UI thead).
onPostExecute() runs on the UI thread, so why I've got "wrong thread"?
This code ran already on more than 150 devices, and more than 100000 times (according to Flurry), and never had this error.
The originating device is Samsung SGH-I997 running SDK 4.0.4
My question is: How could it be?
EDIT:
This all happens in a fragment
i was suffering from the same problem, this is another android framework bug...
what is happening:
in certain circumstances an application can have more than one "looper" and therefore more than one "UI thread"
--side note-- i am using the term "UI thread" in the loosest of senses in this answer, since when people say "UI thread" they usually mean main or entry thread, Android like many of other OS before it, allow for for multiple message pumps (called a Looper in Android, see: http://en.wikipedia.org/wiki/Event_loop) for different UI trees, as such android for all intents and purposes is capable of running more than one "UI thread" in certain circumstances and using that term leads to rampant ambiguities... --end side note--
this means:
since an application can have more than one "UI thread" and an AsyncTask always "Runs on the UI thread" [ref], someone decided [poorly] that instead of the AsyncTask always running on its creation thread (which in 99.999999% of cases would be the correct "UI thread") they decided to use hocus pocus (or a poorly crafted shortcut, you decide) to execute on the "main looper"..
example:
Log.i("AsyncTask / Handler created ON: " + Thread.currentThread().getId());
Log.i("Main Looper: " + Looper.getMainLooper().getThread().getId() + " myLooper: "+ Looper.myLooper().getThread().getId());
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
Log.i("doInBackground ran ON: " + Thread.currentThread().getId());
// I'm in the background, all is normal
handler.post(new Runnable() {
#Override
public void run() {
Log.i("Handler posted runnable ON: " + Thread.currentThread().getId());
// this is the correct thread, that onPostExecute should be on
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
Log.i("onPostExecute ran ON: " + Thread.currentThread().getId());
// this CAN be the wrong thread in certain situations
}
}.execute();
if called from the bad situation described above the output will look something like this:
AsyncTask / Handler created ON: 16
Main Looper: 1 myLooper: 16
doInBackground ran ON: 12
onPostExecute ran ON: 1
Handler posted runnable ON: 16
that's a huge FAIL for AsyncTask
as shown this can be mitigated using a Handler.post(Runnable) in my specific case the duality of my "UI thread" situation was caused by the fact that I was creating a dialog in response to a JavaScript interface method called from a WebView, basically: the WebView had its own "UI thread" and that was the one that i was currently running on..
from what i can tell (without really caring about or reading into it too much) it seems that the AsyncTask class' callback methods in general run off a single statically instantiated handler (see: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.3_r1/android/os/AsyncTask.java#AsyncTask.0sHandler), which means that it is always going to execute on the "main thread" or "entry thread" which they incorrectly refer to as the "UI thread" (which is presumed as any thread where UI interactions take place, eg. multiple threads in this case) this is both shoddy craftsmanship and shoddy documentation from the android team... weak sauce, the sauce is weak
hope this helps you -ck
Had the same issue. Solved in my case
Briefly explanation:
Running AsynckTask for the very first time on non UI thread with looper leads to loading AsyncTask.class and initialization sHandler to handler constructed on that non UI looper.
Now sHandler is connected to that non UI thread for ANY instance of AsyncTask subclasses and onPreExecute, onProgressUpdate and onPostExecute methods will be invoked on that non UI thread (unless AsyncTask.class will be unloaded)
Any attempt to deal with UI inside any of the above methods will lead to crash with android.view.ViewRootImpl$CalledFromWrongThreadException
To avoid such situation one should always run (at least for the very first time) AsyncTask on UI thread in order to let AsyncTask's sHandler-field be initialized with UI's looper
The story:
There were two production apps: A - main android app and B - some utilty app.
After integration app B ito app A we received a lot of crashes:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
for method running from AsynckTask.onPostExecute()
After some investigation it appeared that utility app B used AsyncTask within its HandlerThread
The traces was found in AsyncTask's source code:
private static final InternalHandler sHandler = new InternalHandler();
This is the handler which is used to send onPostExecute() to UI thread.
This handler is static and it will be initialized during class loading i.e. first new AsyncTask() appearance
It means that onPostExecute will always be posted to that thread where new AsyncTask() was called for the first time (unless AsyncTask.class will be unloaded and loaded again)
In my case the flow was something like this:
1 - starting app A
2 - initializing B form A
3 - B creates its own HandlerThread and launches AsyncTask <- now onPostExecute wil be posted to this HandlerThread no matter where from an instance of AsyncTask will be launched in future
4 - create AsyncTask in the app A for a long operation and update UI in its onPostExecute
5 - when executing onPostExecute() the CalledFromWrongThreadException is thrown
Then a friend of mine showed me related documentation from android.developers (Threading rules section):
The AsyncTask class must be loaded on the UI thread. This is done
automatically as of JELLY_BEAN. The task instance must be created on
the UI thread. execute(Params...) must be invoked on the UI thread.
Hope it can help to make clear the situation)
Maybe the reason is Flurry?
I had this exception when I used Flurry 3.2.1. But when I went back to Flurry 3.2.0 I didn't have this exception
Use Flurry 3.2.2 and above.
Placing the following line of code in the Application onCreate should solve the problem:
/**
* Fixing AsyncTask Issue not called on main thread
*/
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
It seems the issue is created when the AsyncTask class is first initiated on a different main Thread which is not our main Thread, I checked it by adding the code in the bottom, to my Application onCreate
new Thread(new Runnable() {
#Override
public void run() {
Log.i("tag","1.3onPostExecute ran ON: " + Thread.currentThread().getId());
Looper.prepare();
new AsyncTask<Void,Void,Void>(){
#Override
protected Void doInBackground(Void... params) {
Log.i("tag","2onPostExecute ran ON: " + Thread.currentThread().getId());
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
Log.i("tag","1.2onPostExecute ran ON: " + Thread.currentThread().getId());
super.onPostExecute(aVoid);
}
}.execute();
Looper.loop();
Looper.myLooper().quit();
}
}).start();
This code will init the AsynTask in a main Thread which is not the application main, and will cause the application to crash in any other AsyncTask which will do any UI on the post-execute. crashing with the CalledFromWrongThreadException
Hope it cleared things a little bit more.
Thanks all for the great help on this.
Where is
runOnUiThread(new Runnable() {
public void run() { /*code*/ } );
in your code
/*
* runs on the ui thread
*/
protected void onPostExecute(String result) {
Activity a = getActivity();
if (S.sHelpEnabled && a != null) {
in = new InstructionsView(a.getApplicationContext());
runOnUiThread(new Runnable() {
public void run() {
RelativeLayout mv = (RelativeLayout) a
.findViewById(R.id.main_place);
mv.addView(in.prepareView());
}
}
};
Try this code. I think this would fix the problem
I think the problem lies in the line Activity a = getActivity(); I think you should do that before going into the AsyncTask

How to stop asynchronous thread after 5 seconds of running

Have to create thread and run it for 5 seconds, then I want to stop. How can I do that?
I can't do anything with time/milliseconds.
THX.
Threading in java is cooperative - you can not forcefully stop a thread. What you can do is signal it to stop (call interrupt() or raise a flag) and then the code willingly stops.
So:
Start running your worker thread. Inside it repeatedly (inside main working loop) check for isInterrupted() AND catch any InterruptedExceptions - exit the thread in this case.
Start a TimerTask to run for 5 sec, then call interrupt() on the worker thread.
Update: poster explained that he already has a working code, he just needs to run it asynchronously without blocking UI.
Solution: setup AsyncTask and run your code inside it's doInBackground() method.
Use the AsyncTask.cancel(true) method.
Sorry for not being clear here. Here is the example I have for synchronous thread.
My function listen() runs for 5 seconds then exits. Listen() is a UDP listener...
Problem I have with this code, it stops my main thread (my phone became unresponsive) until listed() finishes its 5 seconds run. I would like to use asynchronous thread to avoid my phone freezing up. When I said I can't do anything with time, I was trying to say that I can't put some sort of timer in listen() function then measure lapsed time then exit after 5 seconds. Can't do that.
Thread t = new Thread() {
public void run() {
try {
listen();
} catch (IOException e) {
Log.d(TAG, "IOException (Discovery) " + e);
e.printStackTrace();
}
synchronized (this) {
notifyAll();
}
}
};
synchronized (t) {
t.start();
try {
t.join(5000); // 5 sec
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Categories

Resources