Cannot suspend thread to access UI in Android - java

I'm programming a thread that when 10 seconds have passed since beginning it execution it will make visible one component of the UI:
The code is the following:
Thread buttonThread=null; // this is a global variable
[...]
buttonThread = new Thread()
{
#Override
public void run()
{
try
{
super.run();
sleep(10000); //Delay of 10 seconds
} catch (Exception e)
{
}
finally
{
try
{
buttonThread.suspend();
cont.setVisibility(View.VISIBLE);
buttonThread.destroy();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
};
buttonThread.start();
But when I try to execute the buttonThread.suspend() I'm getting a java.lang.UnsupportedOperation exception.
I'm aware that using suspend is unsafe, and that's the reason it's deprecated, but I'd like to check first that suspending the thread does work and doing it by calling .suspend() looks the easiest way.
Could you, please, suggest me some possible solution so the thread shown in the code is suspended?

I'm programming a thread that when 10 seconds have passed since beginning it execution it will make visible one component of the UI:
The thread is overkill here and its use its not justified. Use plain Runnable and post it with required delay (postDelayed()) instead - that would more than enough for your task.

There is plenty of ways of doing something like this in android. The most common one being, using a Handler class like this.
add this import line.
import android.os.Handler;
and use this code to create a new runnable using handler class.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// do your stuff here
}
}, DELAY_IN_MILLI_SECONDS);

Related

Run schedule in new thread

I'm querying an API to create a report and want to load that report 5 minutes later. I want to use a ScheduledExecutorService for that. As I don't want the Executor to block my thread, I'm creating a new thread for that, but am unsure if this is the correct way of doing this. Here's my code:
Thread thread = new Thread() {
public void run() {
log.info("Starting...");
new RequestReport().runScheduledTask(requestId);
}
};
thread.start();
private void runScheduledTask(String requestId) {
log.info("Starting five-minute countdown now...");
ScheduledFuture<?> countdown = scheduler.schedule(() -> {
try {
new GetReportList().run(requestId);
} catch (Exception e) {
e.printStackTrace();
}
}, 5, TimeUnit.MINUTES);
try {
countdown.get();
} catch (InterruptedException | ExecutionException e) {
log.info("catched Exception");
e.printStackTrace();
}
scheduler.shutdown();
}
Is there a better way to run a function 5 minutes after another? Is the way I'm doing this good? What should I change?
BTW, I'm using spring - is there something that could make that better?
ScheduledExecutorService is a good choice, but you use it incorrectly:
First of all, you don't need to create a Thread just to schedule a task from it. It adds nothing to the functionality, only wastes resources.
Second, after calling shutdown() your scheduler will no longer accept tasks, which is bad if you need to generate more than one report.
Third, since your code does nothing after the task completion, you don't need to call get() at all.
So, the only code you need is:
scheduler.schedule(() -> {
try {
new GetReportList().run(requestId);
} catch (Exception e) {
e.printStackTrace();
}
}, 5, TimeUnit.MINUTES);
It will schedule a task and release your thread immediately. The task will be executed five minutes later in a separate thread that is managed by scheduler.
If you need some control on the scheduled tasks (check their states, cancel them etc.), you can obtain Future from schedule() and save it somewhere, but based on the code from your question, you don't need it.
If you'd like to be more 'correct' about the code, you could separate the RequestReport into it's own class implementing the Runnable interface, and pass along an instance of said class to the Thread's constructor

Starting/Calling the same thread multiple times Java Android

I need to call the same thread multiple times in my app. Using my original code, the first time is can be executed just fine. But the second time it crashes - I then learned that each thread shall only be executed not more than one time.
My original piece of code:
View.OnClickListener myClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
mythread.start();
}
};
Thread mythread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
So as I said, it crashes if I try to run it for the second time. So I tried modifying it like:
View.OnClickListener myClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
test();
}
};
private void test(){
Thread mythread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
mythread.start();
}
It works very good; but my question is that whether this is the correct way to do this action or there is a more optimal way to do this?
Also, is it an acceptable thing to call a thread from insider of another thread? (like the way I put stuff on UI Thread inside the new thread of mine)
EDIT:
This is just an example. For my actual code I have heavy math-based simulation to be done which takes 10sec to be done. Based on the results that will be shown to the user , they may want to change their input parameters and let the simulation run again. This will happen several times.
In addition to the other good answers about using AsyncTask or runOnUiThread(), you could define a private member as a Runnable, like this:
private Runnable mytask = new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
Then, whenever you want to run it, do
new Thread(mytask).start();
There is nothing bad with that but I think a better way would be using AsyncTask. It is exactly designed for this cases.
You can use AsyncTask multiple times just creating a new one like this new MyAsyncTask().execute(""); (source from here)
Also, is it an acceptable thing to call a thread from insider of another thread? (like the way I put stuff on UI Thread inside the new thread of mine)
runOnUiThread exists solely for that purpose. But there are usually much better ways (e.g. AsyncTask) so using this method is probably a bad idea.
my question is that whether this is the correct way to do this action or there is a more optimal way to do this?
You should not use a thread just to schedule future tasks. They are useful to execute something in parallel to the main thread but add lots of potential errors (try rotating the screen between it prints running..finished, could crash)
I would use a CountDownTimer in your case.
Or a Handler, examples e.g. here: Schedule task in android
From the provided code I assume that you want to perform an UI operation before and after your long mathematical computation. In such as #Andres suggested, AsyncTask is your best buy. It provides method onPreExecute, onPostExecute which runs on UI thread, and thus no need for explicitly calling runOnUiThread.
Key concepts :
You can't start an already started thread. This will return in an IllegalStateException. If you need to perform same task again, you should create a new instance.
If you find yourself creating several instances of a thread (even AsyncTask), since you need to run same task again and again, I would suggest you to use Thread Pool or simple Java Executor Service. Create a singleThread or may be pool and post your runnable onto executorService and it will take care of the rest.
Inter-Thread or Inter-Process communication is quite common requirement.

Wait for thread to finish in Java

I have some code which executes a download in a separate thread, created so that the JFrame GUI will continue to update during the download. But, the purpose is completely defeated when I use Thread.join(), as it causes the GUI to stop updating. I need a way to wait for the thread to finish and still update the GUI.
You can have the task that does the download also fire an event to the GUI.
For example:
Runnable task = new Runnable() {
public void run() {
// do your download
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// call some method to tell the GUI that the download finished.
}
});
}
};
and then to run it, either use an Executor (preferred method) or a raw thread:
executor.execute(task);
or
new Thread(task).start();
As pointed out in the comments, you'd generally use a SwingWorker to do this kind of thing but you can also do the manual approach outlined above.
SwingWorker provides a doInBackground method where you would stick your download logic in, a done method where you would stick in code to notify the GUI that the download finished and a get method to get the result of doInBackground (if there was one).
E.g.,
class Downloader extends SwingWorker<Object, Object> {
#Override
public Object doInBackground() {
return doDownload();
}
#Override
protected void done() {
try {
frame.downloadDone(get());
} catch (Exception ignore) {
}
}
}
(new Downloader()).execute();

Running two expensive database calls in parallel

I have (say) 2 functions which does a db-hit to fetch a lot of data. Since the two functions are executed one after the other (by the same thread), the time taken is T(f(1)) + T(f(2)). How can I execute the two functions in parallel (by means of creating 2 threads) so that the total time taken is: T(max(T(f1), T(f2))
I am done writing my complete java swing application and want to optimize it for performance now. Appreciate any insight, and excuse if the question is too naive.
Thank you!
You haven't said whether you need any return values from your functions, but given the fact that they access the database it seems very likely. A pretty nice and simple solution to that is to use Executors and Futures.
A full code example is here:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FuturesExample {
public interface ReturnTypeOne {}
public interface ReturnTypeTwo {}
public void runTwo() {
ExecutorService executor = Executors.newFixedThreadPool(2);
// Dispatch two tasks.
Future<ReturnTypeOne> first = executor.submit(new Callable<ReturnTypeOne>() {
#Override
public ReturnTypeOne call() throws Exception {
// Work, work, work...
return null;
}
});
Future<ReturnTypeTwo> second = executor.submit(new Callable<ReturnTypeTwo>() {
#Override
public ReturnTypeTwo call() throws Exception {
// Work, work, work...
return null;
}
});
// Get the results.
try {
ReturnTypeOne firstValue = first.get();
ReturnTypeTwo secondValue = second.get();
// Combine the results.
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
It consists of two sections. First in which two tasks are submitted into the thread pool.
Each ExecutorService.submit() call returns immediately a future value of the task computation. Tasks are dispatched immediately at submit() call and they run in the background. Of course you can dispatch more than two tasks.
In the second section the values of futures are obtained. What happens is that the call
to Future.get() blocks the current thread until the value is computed. It does not mean
that any task is blocked, they all are running, the thread just waits until a given task completes and returns a value. Once the first value is returned, the second Future.get() call is made. In this case, it may or may not block. If the second task has already finished (possibly before the first task) the value is returned immediately. If the second task is still running, the call blocks the current thread until the value is computed.
What the above boils down to is that your main thread will only wait as long as the longest
running task. Just what you needed.
You can dispatch 2 threads like this:
new Thread(new Runnable()
{
#Override
public void run()
{
// TODO Place your "f(1)" code here...
}
}).start();
new Thread(new Runnable()
{
#Override
public void run()
{
// TODO Place your "f(2)" code here...
}
}).start();

Learning Threads - Running a method only after the other has finished

In my button execution, I am calling 2 methods.
plotButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
startPrinterListOperation();
showAplotPlotterDialog();
}
});
The startPrinterListOperation(); takes some time to complete its task. But I do not want the method showAplotPlotterDialog(); to run until the first one has completed. So I am trying to use thread management to achieve this. Here is what I have tried.
plotButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Thread t = new Thread() {
public void run() {
startPrinterListOperation();
}
};
t.start();
try {
t.join();
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
showAplotPlotterDialog();
}
});
But the second method stills starts before the first one has finished.
Extending on my comment: Seems like startPrinterListOperation launches an asynchronous operation and finishes instantly, evidented by the join succeeding.
If the launched async op is out of your control, then you might be able to observe it finishing via some callback, polling, etc. Then you may employ something like the following in startPrinterListOperation:
void startPrinterListOperation() {
final CountDownLatch c1 = new CountDownLatch(1);
launchTheAsyncOp(new SomeCallback() {
void x() {
c1.countDown();
}
});
try {
c1.await(999, TimeUnit.SECONDS)
}
catch (InterruptedException e) {
throw new MyRuntimeException("user didn't finish the op in 999 seconds, fail");
}
}
I would not bother with threads, this will just make your program overly complicated.
Can you edit the startPrinterListOperation() method?
I would instead add showAplotPlotterDialog(); to the end of the startPrinter method, and the last last thing the method does.
Answering your general question in the title, you have a master thread that calls your two methods directly, so that the second method waits for the first method to complete.
I understand that in your specific case, the first method runs for a while, and you would prefer that the user not have to wait.
You should call a generatePrinterList() method in a separate thread while you're constructing the GUI. You do this because your GUI users are very likely to print or plot, and the printer list is not likely to change while the user is using your GUI.
Odds are that the generatePrinterList() thread will finish long before your user has to print or plot. But just to be sure, the thread has to have a way of reporting back that the thread is completed. I use a boolean isCompleted that can be read with a public isCompleted() method.
The isCompleted() method could have a thread sleep loop if you want, so it always returns true. In this case the method doesn't have to return anything.

Categories