I have created a thread (threadName = Original) in onCreate() method of activity in android app. Now inside this thread (inside runnable), there is a for loop in which I created some new threads and then executed the threads in executorService like executorService.execute(thread), for each of them. After that, I created a timer in which I am checking that thread (Original) isAlive() and when the Thread.isAlive() is false then I call my recycler View.
Normally a thread does not die if we do not call executorService.shutdown(). But in android, it dies without the executorService being shutdown. Why this behaviour is seen in android studio?
Check with this example, our program will run indefinitely
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
}
});
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(thread1);
}
The problem is that the 'original' thread finishes once it submits new tasks to the executor, unless you block it manually. This example shows how to wait until all tasks are finished or until a specified time-out occurs:
public static void main(String[] args) {
Runnable r = () -> {
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
Runnable run = () -> {
try {
Thread.sleep(15000);
System.out.println("Stopping Thread " + Thread.currentThread().getId());
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
};
service.submit(run);
}
try {
service.shutdown(); // shuts down once all submitted tasks complete
service.awaitTermination(18, TimeUnit.SECONDS); // blocks until all tasks complete after shutdown request or until time-out occurs
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
};
Thread original = new Thread(r);
original.start();
System.out.println("is Alive? " + original.isAlive());
while (original.isAlive()) {
// blocks until thread is not alive anymore
}
System.out.println("Original Thread Stopped");
}
I'd like to point out that it is very inefficient to use a for/while loop to constantly check whether a thread is still alive or not. Instead you could implement a listener that is invoked once all threads are finished.
Here is the executor service
ExecutorService service = Executors.newCachedThreadPool();
service.shutdown() - it means cannot execute anymore runnable, it does not mean that the executor is dead.
service.awaitTermination(20, TimeUnit.SECONDS) - it means that the program will wait for 20 seconds and then it will die without finishing work. And also if the work is done before 20 seconds then everything is fine and it will die.
So in my case, after I used awaitTermination then it worked fine. My activity now waits for executor service to complete all the tasks.
Related
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 button that when clicked calls sendFile() to send a file to a server. In the function I am creating a thread, then sending the file in the thread. My question is what happens to the thread after the file is sent? Will the old threads continue to run as I create more threads?
void sendFile(File f) {
Thread mythread = new Thread(new Runnable() {
#Override
public void run() {
// code to send the file
}
}
mythread.start();
}
From here
A thread can die in two ways: either from natural causes, or by being
killed (stopped). A thread dies naturally when its run method exits
normally. For example, the while loop in this method is a finite
loop--it will iterate 100 times and then exit. public void run() {
int i = 0;
while (i < 100) {
i++;
System.out.println("i = " + i);
} } A thread with this run method dies naturally after the loop and the run method complete.
So when run finishes the thread would die i.e stop !!
I have a service for file downloading in my service I have a Asynctask that do downloding and i am using from a content provider for save status of files .my problem is that when asynctask run any other asynctask cant run in app all of them wait till download task finish.any idea?
As of honeycomb version, AsynchTasks run in a serial executor. So if you plan to run many download jobs in parallel then what you need to do is to use an ExecutorService in your Asynchtask to do jobs in parallel.
You can also set the executor type in AsynchTask to parallel instead of sequencial when you create it, but i wont recommend that.
here are some code snippets using a Loader:
private ExecutorService executorService;
private static final int MAX_RUNNABLE_THREADS = 800;
private static final int KEEP_ALIVE_TIME = 6;
//in constructor and probably in onStartLoading...
if(this.isNetworkfast){
this.executorService = new ThreadPoolExecutor(0, MAX_RUNNABLE_THREADS
, KEEP_ALIVE_TIME
, TimeUnit.SECONDS
, new SynchronousQueue<Runnable>()
);
}else {
this.executorService = Executors.newFixedThreadPool(3);
}
//in onReset
this.executorService.shutdownNow();
try {
if (executorService.awaitTermination(20, TimeUnit.SECONDS)) {
Log.i(TAG, "executorService shutdown completed.");
}else{
Log.e(TAG, "executorService shutdown failed to finish completely.");
if(this.isErrorReportingEnabled){
this.errorMap.put("error_" + (++errorCount), "executorService shutdown failed to finish completely.");
}
}
} catch (InterruptedException e) {
Log.e(TAG, "DownloadNseQuotesAsynchTaskLoader executorService shutdown interrupted.");
if(this.isErrorReportingEnabled){
this.errorReporter.reportCustomMessagesWithException("exception_" + (++errorCount)
, "DownloadNseQuotesAsynchTaskLoader executorService shutdown interrupted.", e);
}
}
//in loadInBackground....
//do your processing to determine the number of workers/runnables needed and based on that
final CountDownLatch latch = new CountDownLatch(number of workers);
MyWorker worker = new MyWorker(latch, data set....);
this.executorService.execute(worker);
//and later in the same method we wait on the latch for all workers to finish
try {
latch.await(); //blocks the current thread until the latch count is zero
//all Workers have finished, now read in the processed data if you want
for (MyWorker worker : workers) {
SomeDataVO dataVO = worker.getData();
.......
}
} catch (InterruptedException ie) {
Log.e(TAG, "Interrupted exceltion while await on CountDownLatch running", ie);
if(this.isErrorReportingEnabled){
this.errorReporter.reportCustomMessagesWithException("exception_" + (++errorCount)
, "Interrupted exception while await on CountDownLatch running", ie);
}
}
This is not the complete piece but should be enough to give you ideas about how to use it.
All AsyncTasks background work runs serially in a background worker thread, it is designed to solve short problems.
As you probably using a long running connection, you should do this on a Thread inside a separate Service. A simple approach would be receive the connection parameter by Intent and start a new thread directly on startCommand().
I am referring to http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/AlarmService_Service.html
There the runnable of the thread looks like this
Runnable mTask = new Runnable()
{
public void run()
{
Log.v("service", "thread is running after 5 min");
// Normally we would do some work here... for our sample, we will
// just sleep for 30 seconds.
long endTime = System.currentTimeMillis() + 15*1000;
while (System.currentTimeMillis() < endTime)
{
synchronized (mBinder)
{
try
{
mBinder.wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
}
} // Done with our work... stop the service!
AlarmService_Service.this.stopSelf();
}
}
I admit that I have some problems with the concept of synchronized... The thread runs the while loop to wait 15s, within that loop I have wait for 15s. So how would the runnable look like if I just want to write a log entry e.g. Log.v(TAG,TEXT);? What would change if I want to write a new entry into my own database table?
Thanks, A.
If you just want a log statement then the following will work fine
Runnable mTask = new Runnable()
{
public void run()
{
Log.v("TAG", "Some verbose log message");
}
}
Whether you need to use synchronized on an object depends on whether object is thread-safe or not. If it is not thread-safe, then you will need to ensure that only one thread access the object at a time by using a synchronized block. In your example mBinder is not thread-safe, so in order to call the wait method of the binder you need to ensure that you are the only thread accessing it.
A runnable is most often used to execute code in a different thread, so that long running operations (such as IO, but in this case just waiting) do not block the UI thread.
Simply replace
try
{
mBinder.wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
}
...with the code you want to execute?
Synchronized is just to assert that only one process accesses the thread at one time.
Is it possible for a background thread to enqueue a message to the main UI thread's handler and block until that message has been serviced?
The context for this is that I would like my remote service to service each published operation off its main UI thread, instead of the threadpool thread from which it received the IPC request.
This should do what you need. It uses notify() and wait() with a known object to make this method synchronous in nature. Anything inside of run() will run on the UI thread and will return control to doSomething() once finished. This will of course put the calling thread to sleep.
public void doSomething(MyObject thing) {
String sync = "";
class DoInBackground implements Runnable {
MyObject thing;
String sync;
public DoInBackground(MyObject thing, String sync) {
this.thing = thing;
this.sync = sync;
}
#Override
public void run() {
synchronized (sync) {
methodToDoSomething(thing); //does in background
sync.notify(); // alerts previous thread to wake
}
}
}
DoInBackground down = new DoInBackground(thing, sync);
synchronized (sync) {
try {
Activity activity = getFromSomewhere();
activity.runOnUiThread(down);
sync.wait(); //Blocks until task is completed
} catch (InterruptedException e) {
Log.e("PlaylistControl", "Error in up vote", e);
}
}
}