OutOfMemoryError Java heap space when using timertask - java

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.

Related

Java UI thread freezing despite code being in separate thread

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();

Dispatch from GLFW's main thread using LWJGL

I am trying to call GLFW.glfwPollEvents() in an asynchronous task that runs every tick (1/30th of a second in this case). This ticking timer effectively controls when every action in the app takes place.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
//... more code ...
GLFW.glfwPollEvents();
//... more code ...
}
}, 33, 33);
But, this does not work because
This function may only be called from the main thread.
(from the documentation)
How can I call this on the main thread? When it isn't run on the main thread, the application crashes. I'm looking for something like
GLFW.dispatchMainThread(new GLFWRunnable(){
public void run(){
//...
}
});
This is possible to do in swing and awt by using
EventQueue.invokeLater(new Runnable(){
public void run(){
//...
}
});
But the same code doesn't work for GLFW.
How can I run a task on GLFW's main thread using LWJGL without using a while(true) loop on the main thread?
Since GLFW's main thread must be the same as the application's main thread (a limitation in GLFW; that's where it puts the OS message queue that is handled differently by swing/awt it seems - see my answer here) I would do things the other way around.
My main thread would have the forever loop (probably using glfwWaitEvents so as not to eat CPU time needlessly). I would then post any events that were app-specific to another thread that does the processing. Your message processing is now decoupled from your message receiving.
This way I don't have to wait for 1/30th of a second to get OS messages (it always frustrates me when an app lags opening a menu, registering a click, or arrowing through a list).
Your update thread can even sleep for 1/30th of a second (or less, sleeping again if not enough time has passed or not if a second high-priority queue needs work) and only wake up to check for queued events as an extremely simple scheduling method.
The answer I linked to above has a link to an LWJGL Multithreaded Demo that does something very similar. Their renderLoop would be your updateLoop and would draw from a queue and do processing before going to sleep again instead of updating and presenting graphics.

Android - how to prevent UI lag via Handler?

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);
}
};`

Are methods called from a separate thread, run on the calling thread?

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).

Java timer doesn't run when using JNA call to Win32 WaitForSingleObject()

I'm trying to terminate the JNA call to WaitForSignleObject() with Timer that interrupts the current thread:
final Thread thread = Thread.currentThread();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
thread.interrupt();
}
}, 3000);
try {
Kernel32.INSTANCE.WaitForSingleObject(processInfo.hProcess, Kernel32.INFINITE);
...
} catch (InterruptedException e) {
}
The problem is that TimerTask.run() is not called after 3 seconds have passed as expected, it's called only after WaitForSingleObject() exits itself. What am I doing wrong?
Thanks!
Thread interruption mechanism is a Java-specific feature, so it's no surprise that native code doesn't respect it.
If all you need is a timeout, you can use the second argument of WaitForSingleObject() instead. If you need more complex logic, you can create an event to notify waiting thread about interruption, and use WaitForMultipleObjects() on that event and your hProcess.
Quite a few mistakes in that simple code;
During run() the code interrupts the current calling thread - useless, you want the thread making the native call.
You need to handle the interruption of the native call itself.
Below link to how to properly handle from the java side.
Detecting thread interruption with JNA native wait call (Windows)
On WinAPI side: depending on your case you may need CloseHandle, SetEvent or whatever notification you need.
Then after returning from WaitForSingleObject check the object state and throw InterruptedException if you have to.
In looking at Microsoft's documentation for WaitForSingleObject, there's a suggestion that you might to think about WaitForSingleObjectEx instead (in order to enter an "alertable wait state").
The problem is that TimerTask.run() is not called after 3 seconds have
passed as expected, it's called only after WaitForSingleObject() exits
itself. What am I doing wrong?
The simple answer: You're making a blocking call to the operating system. While your thread is blocked, a TimerTask in that thread will not fire.
Even if you ran the TimerTask on another thread, it is unlikely the interrupt would work, since Thread.interrupt is a Java specific feature (as was pointed out by #axtavt).
If you would like more help, please create another posting and explain why you need to do this and what your constraints are (something more specific than "...it breaks my API"). Perhaps we'll be to find an alternative approach.

Categories

Resources