I'm running some webcam captures in a thread like so:
class Capture implements Runnable {
#Override
public void run() {
while(true){
//capture images
//sleep 5 seconds
}
}
//To actually start the capture
new Capture().run();
I'm doing this constantly, so I expect to still be able to perform UI functions like clicking on buttons while this is going on, but that's not the case. The x button on my JFrame is unresponsive, and same with other UI components.
Do I need to do something other than just using a separate thread? Doesn't seem to be working for me. Thanks
You have just implemented Runnable. You haven't started a Thread to do the job. Try this:
new Thread(new Capture()).start();
Also consider Timer class for such job.
This is happening because you are calling the run method but not starting the Thread when you do new Capture().run(); you are not even creating an instance of the Thread
Do I need to do something other than just using a separate thread?
yes, create and start the thread doing instead
new Thread(new Capture()).start();
Related
I've got a Handler that runs a runnable task every 2 seconds. It runs a fairly intensive task (executes a shell command). Every time the I run handler.postDelayed(update, 2000); the user interface lags (for 2 seconds). How do I stop this lag?
I know there's lag because I have a dynamic interface, so I can move around a view and when the handler is run the interface becomes unresponsive for the 2 seconds.
Is there a way to go around this?
You are doing this work on the main UI thread, which is not acceptable for your user to have a good experience, as you have already identified.
You can instead create a new background thread for your handler to run any posted runnables on, which will take the least amount of code change:
mHandlerThread = new HandlerThread("YourHandlerThread");
mHandlerThread.start();
handler = new Handler(mHandlerThread.getLooper());
// Now post your runnable, as before
handler.postDelayed(update, 2000);
Just keep in mind that you cannot touch any UI elements from this thread, as that is not allowed by Android.
when the handler is run the interface becomes unresponsive for the 2 seconds
That means that you are doing two seconds' worth of work on the main application thread. Doing 2 milliseconds' worth of work is more appropriate.
The Runnable that is passed to postDelayed() has its run() method called on the main application thread. If this work will take more than a millisecond or two, you should be using something other than Handler and postDelayed() for your every-two-seconds work, such as a ScheduledExecutorService.
Handler is a way to run code on the UI Thread in Android.
If you don't need your code run on the UI Thread, you may want to consider just making your own Thread or using an Executor.
I've fixed it. Thanks to everyone notifying me that the Handler runs on the UI thread...
I've now run a separate thread to update the variable used in the handler task:
double p = 0;
public void z(){
Thread t = new Thread(){
#Override
public void run(){
p = a.b();
}
};
t.start();
}
Runnable y = new Runnable() {
#Override
public void run() {
z();
c.setText(String.valueOf(p));
d.setProgress(Float.valueOf(String.valueOf(p / 100)));
handler.postDelayed(this, 2000);
}
};`
This is weird: When I start a schedule using timer.scheduleAtFixedRate, it takes a long time and then throws a OutOfMemoryError: Java heap space, but if I just called the timerTask.run() method in the main thread, it works just fine.
The method I called is not open-source, so I cannot just paste it out. But could anyone help me analyse some possibilities on this scenario. What is the difference between running it in a timerTask thread and running it in the main thread?
Thanks a lot!
The code snippet is just as simple as follows:
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
AModule.load(tmpFilePath); //not open-source
}
}
timer.scheduleAtFixedRate(task, new Date(), 1*60*1000); //OOME
//If I change the upper code to:
task.run() //it just works fine
The AWT timer runs in its own thread. If by "main thread" you mean the UI thread, or event queue, then:
Perhaps your closed source code is accessing Swing some how. Swing components should only be accessed from the event thread. You might have trouble when running in the timer yet always run fine in your main thread.
If that's the case you're lucky. Calling Swing from another thread usually works. I never have problems till I'm demoing or the client tries to use it. And the problems are often not repeatable.
I've been using threads for 2-3 days now, and I've got a quick question regarding methods. I'm making an Android application and it starts off with the main UI thread (let's call it the "UI Thread" for clarity). I'm spawning a new thread using the following code:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
someMethod();
}
});
thread.start();
My question is, will someMethod() also run on the new thread that I just created because I'm calling it from there? Or will it run on the UI thread? For reference, someMethod() is located outside outside of the method that's creating the new thread.
If someMethod() won't run on the new thread, how do I make it do so? Thanks.
will someMethod() also run on the new thread that I just created because I'm calling it from there?
Yes, that is exactly what happens. The method is just code. It's independent of the thread-of-control that happens to be running in it at a given point and time. This also means that there could be multiple threads executing that code at any given point in time if there are multiple cpu/cores.
You should take a look at Callable<V> and Future<T>, there you can call methods, that are not processed on the calling thread. You shouldn't work with threads anyway nowadays.
There are more modern approaches available.
Here is a link that should give you an idea http://www.vogella.com/articles/JavaConcurrency/article.html#futures
All of the actions taken by run, including calling someMethod, stay on the new Thread unless that code tells Java to run something in another thread (like with invokeLater or by using an Executor).
Regarding Java Andriod Handlers:
handler.post(new Runnable(){
public void run() {
// do stuff
}
});
From what i understand this gets run on the whatever thread the handler was instantiated on. so lets say in Android i instantiate the handler on the main thread, my question then is what is the point of the runnable ? your adding a task to the messaging queue of the main UI thread, why not just skip the runnable and create a method since your on the main thread already. I've seen programmers doing this and i want to know why ?
I understand we can do Thread genThread = new Thread(new myRunnable()); but i want to know if there is any value of a Runnable on the main thread.
Sometimes you want to run some code but you don't want it to run immediately, you want to defer it. One of the most common uses for this in my experience is when you are in the layout phase and you want to "queue" up something to happen once the layout phase is done. For this you simply post a Runnable to the UI thread's message queue and it will get put at the end of the message queue...which is exactly where you want it.
Another common use case is if you want to find out the size of a view from onCreate. In onCreate the view hasn't been measured yet so this won't work:
Log.d(TAG, view.getWidth());
Instead you can do this:
view.post(new Runnable() {public void run() {Log.d(TAG, view.getWidth());}}) ;
I would recommend using AsyncTask<> rather than Handlers as they are easier to understand and make for cleaner code. I know that I am diverting from the original question posted but this is just a suggestion. If you want to know more about AsyncTask<> below is the link.
AsyncTask
I have read that the main UI thread in android should not call sleep.
However, my application needs to :
call thread1 from main UI thread
call thread2 from main UI thread.
Use the output (2 images) of the 2 thread, add them and then display them.
I am using Thread.sleep() so that the main thread waits thread1 and thread2 till they are done. However mImageview.setbitmap is not working after i call it in the main thread (after sleep).
can u pls advise me how i should do this?
Multithreading in Android should be done Asynchronously. For this purpose, you should use the AsyncTask-class.
For your case, you would for example create a taks to load (or process) those two images. While the process is running (in another thread, off the UI-thread), you could show a ProgressBar that shows to the user that your application is currently busy (this is then done on the UI-thread).
When the task has finished, you get the results (your two images) from the task, hide the progress-bar and show everything to the user.
Despite the fact that a non-reacting GUI always has the feeling that your application frooze, if a UI-Thread is blocked for more then 5 seconds (which is a looong time), your application will be Force-closed as it is not "reacting" (and an ANR will be raised).
It's not just Thread.Sleep(). In the GUI thread, do whatever you need to to start the two threads/tasks/whatever and then exit the event handler.
Do not wait in GUI event-handlers! Not in Java, C++, C, Delphi, anything. Use an async task, or a Handler, and signal to the GUI thread. Thread 1 signals that it is done, thread 2 signals that it is done. In either case check to see if the data has been returned by the other thread. If it has, you have both sets of returned data and so you can add them and display them.
Do not wait in GUI event-handlers.
You can simply use Threads And Handlers for this purpose.
Here is a small demo for this,
Create a Handler in your onCreate like this,
Drawable d=null;
Handler handler=new Handler()
{
public void handleMesaage(Message msg)
{
if(msg.what==0)
{
imageView.setBackgroundDrawable(d);
}
}
};
And now call Your Thread like this,
Thread t=new Thread(new Runnable()
{
#Override
public void run() {
InputStream is = (InputStream) new URL(url).getContent();
d = Drawable.createFromStream(is, "src name");
handler.sendEmptyMessage(0);
}
});t.start();
I would suggest to use the ExecutorService. Here is how
Create the two image loading activities as Runnable tasks.
Execute them with the ExecutorService.
Use ExecutorService.awaitTermination(); for the main thread to wait for Runnable tasks to complete. Its documentation reads
Blocks until all tasks have completed execution after a shutdown
request, or the timeout occurs, or the current thread is interrupted,
whichever happens first.
This is the Asynch way of doing it and I guess should be preferred.