How to ensure a Thread won't delay in Java? - java

I wrote a multi threading programme, which have two to four thread at the same time.
One of the thread is time critical thread, it will be called every 500 milliseconds, it is not allow to delay more than 10 milliseconds. But when other thread have more loading, I find that some delay, around two millisecond is occurred. (Print the timestamp to show it) So, I worry that after running for a long time it will delay more than 10 milliseconds, except from check the timestamp, and adjust the looping interval to make sure the time is not delay more than 10 milliseconds, is there any way to make it safe?
Thanks.

Sounds like you need Real-Time Java

If timing is critical, I use a busy wait on a core which is dedicated to that thread. This can give you << 10 micro-second jitter most of the time. Its a bit extreme and will result in the logical thread not being used for anything else.
This is the library I use. You can use it to reserve a logical thread or a whole core. https://github.com/peter-lawrey/Java-Thread-Affinity
By using isolcpus= in grub.conf on Linux you can ensure that the logical thread or core is not used for any else (except the 100 Hz timer and power management which are relatively small and < 2 us delay)

You can set your threads priorities:
myCriticalThread.setPriority(Thread.MAX_PRIORITY);
otherThread.setPriority(Thread.NORM_PRIORITY); // the default
yetAnotherThread.setPriority(Thread.MIN_PRIORITY);
It won't really guarantee anything though.

There is no guarantee that your thread isn't delayed, because the OS may decide to give other processes precedence (unless you put effort in setting up a complete real-time system including a modified OS). That being said, for basic tasks, you should use a ScheduledExecutorService like this:
class A {
private final ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
public void startCriticalAction(Runnable command) {
this.exe.scheduleAtFixedRate(command, 100, 100, TimeUnit.MILLISECONDS);
}
public void shutdown() {
this.exe.shutdown();
}
}
The executor service will do its best to execute the task every 100ms. You should not develop this functionality yourself, because a lot of things can go wrong.

Creep up on the timeout:
waitFor(int timeout)
{
dateTime wallTimeEnd;
wallTimeEnd=now()+(msToDateTime(timeout));
int interval=timeout/2;
while(true){
if(interval>10){
sleep(interval);
interval=dateTimeToMs(wallTimeEnd-now()) / 2;
}
else
{
do{
sleep(0);
interval=dateTimeToMs(wallTimeEnd-now());
}while(interval>0);
}
}
This only wastes a core for 5-10ms

Related

How to approach a Java event queue

Hello everyone and thanks for the time you dedicated in advance!
I have a problem I'm not sure how to approach in Java. Let's say I have a user interface that creates events that have to be "executed" in a specific time in the future, which may vary from a couple of minutes in the future to several days.
I have though of creating a class (let's say EventHandler) that implementa Runnable, and then a ConcurrentLinkedList that stores those instantiations ordered by the time they should be executed, from least in advance to most in advance. After that, a thread that peeks the queue, and If system time is greater than expected execution time, start the process.
Problem is, aside of concurrency problems associated with list, that the peek thread consumes CPU time. So I was wondering if there is a more elegant solution, considering there may be hundreds of events scheduled in a single second interval. Also, I'm using Hibernate with MongoDb to store stuff, if that affects at all.
Thank you!
EDIT: I'm open to all other solutions you may think of, as long as it solves the "queue events and execute them in the time they are set to"
A straightforward approach is to use ScheduledThreadPoolExecutor.
int corePoolSize = 1;// for sequential execution of tasks
// for parallel execution use Runtime.getRuntime().availableProcessors();
ScheduledThreadPoolExecutor executor = ScheduledThreadPoolExecutor(corePoolSize);
...
Runnable command1 = ...
executor.schedule(command1, 2, TimeUnit.MINUTES); // execute in couple of minutes
Runnable command2 = ...
executor.schedule(command2, 7, TimeUnit.DAYS); // execute in 7 days

Is fork / join multithreaded?

If I have 2 CPUs and schedule 1000 tasks for the fork / join framework to work on, will the tasks be executed in a maximum of 2 at a time, or will more tasks be executed in parallel on the same CPU? (say, maybe one task is waiting for I/O, in which case the CPU would become idle and another thread could run)
If you do not include any restriction yourself, none will be applied and Java will fork as many threads as it can (maybe all 1000 depending on system restrictions). This is not ideal. If you're doing a computation which is likely to have some IO time but not be IO bound even at large amounts of concurrent processing, you might be able to justify running one more thread then the available number of CPUs. Running all 1000 at once would not be wise.
If I have 2 CPUs and schedule 1000 tasks for the fork / join framework to work on, will the tasks be executed in a maximum of 2 at a time, or will more tasks be executed in parallel on the same CPU?
If you have a dual core CPU, you can only actually execute 2 threads at once.
According to the ForkJoin documentation:
A ForkJoinPool is constructed with a given target parallelism level;
by default, equal to the number of available processors. The pool attempts to maintain enough active (or available) threads by
dynamically adding, suspending, or resuming internal worker threads,
even if some tasks are stalled waiting to join others. However, no
such adjustments are guaranteed in the face of blocked IO or other
unmanaged synchronization.
So it will probably run them two at a time on your 2 CPUs, possibly four at a time if the CPUs are hyperthreaded (I'm not certain). If you aren't happy with the default level of parallelism, you can specify a requested level of parallelism by calling the ForkJoinPool constructor that takes the level of parallelism as a parameter.
Is hyperthreading enabled on the cpu? If so you may run 2+ processes at the same time.
Hyper-threading works by duplicating certain sections of the processor—those that store the architectural state—but not duplicating the main execution resources. This allows a hyper-threading processor to appear as two "logical" processors to the host operating system, allowing the operating system to schedule two threads or processes simultaneously.
Hyper-threading # wikipedia
I made a test to verify this:
import java.util.concurrent.*;
public class Test {
private static class TestAction extends RecursiveAction {
private int i;
public TestAction(int i) {
this.i = i;
}
protected void compute() {
if (i == 0) {
invokeAll(new TestAction(1), new TestAction(2), new TestAction(3),
new TestAction(4), new TestAction(5), new TestAction(6));
return;
}
System.out.println(i + " start");
try { Thread.sleep(2000); } catch (Exception e) { }
System.out.println(i + " end");
}
}
public static void main(String[] args) {
new ForkJoinPool().invoke(new TestAction(0));
}
}
The results of that running with the reference Oracle implementation is:
1 start
6 start <- wait 2 seconds
1 end
2 start
6 end
5 start <- wait 2 seconds
2 end
3 start
5 end
4 start <- wait 2 seconds
4 end
3 end
The same behavior is consistent on both Linux and Mac OS X.
So the answer to the question is: yes, the tasks will be executed on exactly the number of CPUs specified by the parallelism parameter (or the total available CPUs by default). If CPU time becomes available and the tasks simply block waiting for something, then the framework will do nothing automatically to run other tasks.
Since the documentation I've seen so far is pretty vague about what exactly the framework is supposed to do if the CPU is free, this could be an implementation detail.
By default, the Fork/Join Framework tries to maintain the number of threads equal to one less than the number of cores (if a single core machine, then one thread is created). You can see this code in makeCommonPool method in ForkJoinPool class.
If you think that this under-utilises your CPU, you can provide a custom value for parallelism.
But most interestingly, there is a way to make ForkJoinPool create more threads when the current thread occupying the CPU blocks on IO. All you have to is to implement the code block which actually blocks on the IO inside an implementation of the block method of the ForkJoinPool.ManagedBlocker object, and pass that ManagedBlocker object to the managedBlock method of the ForkJoinPool class. When this is done, the ForkJoinPool checks if the current thread calling this method is an instance of a ForkJoinPoolWorkerThread. If it is, the ForkjoinPool compensates by creating new threads which can take over the CPU.
ForkJoinPool fjp = ForkJoinPool.common();
Runnable task = new Runnable(){
public void run(){
//Some cpu-intensive code
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker(){
public boolean isReleasable(){
//return true if an IO/blocking operation is to be done.
}
public boolean block(){
//Do an IO Operation here
//return true if all blocking code has finished execution.
//return false if more blocking code is yet to execute.
}
});
//Some more CPU intensive code here
}
};
fjp.submit(task);

Java Threads and high cpu usage

I've done some search here and couldn't find an answer, so I think it's better to ask.
I'm running a little bit expensive algorithm in a simple Java swing application. Let me describe the structure:
In my JPanel run() method:
public void run() {
while(true) {
Algorithm alg = new Algorithm(signal);
new Thread(alg).start();
//Wait for algorithm to finish
signal.await(alg);
updateInterface();
Thread.sleep(60L);
}
}
Algorithm loops through the pixels of a .JPG file, then loops through another large Integer array (length ~ 12000) and returns. There are very no extra expensive calculationslot. I call Thread.sleep(60L) in the Algorithm run() method also.
The udpateInterface() method is very fast, just draw some java.awt.Polygon objects.
Even though I'm calling Thread.sleep(60L), the CPU usage is about 160% on my Mac Book (2.4 GHz Intel Core 2 Duo, Mem 4GB 1067).
Is there a way I can run this without melting my computer? I'm using CountDownLatch as
a wait notify mechanism.
Thanks!
I would use the following pattern to schedule a repeating task.
private ScheduledExecutorService executorService = null;
public void start() {
if (executorService != null && !executorService.isShutdown()) return;
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
Algorithm alg = new Algorithm(signal);
alg.run();
updateInterface();
}
}, 0, 60, TimeUnit.MILLISECONDS);
}
public void stop() {
if (executorService != null)
executorService.shutdown();
}
160% CPU usage is relative to a single core of your machine -- that is, the maximum possible on your machine is 200%, because it has two cores. You're not melting your processor.
There's no point starting another thread if all you're going to do afterward is make the current thread wait for the other one to finish. You might as well just run the algorithm in the thread you already have; either way, you won't proceeed to updateInterface() until the algorithm is done.
As others have pointed out, after the algorithm finishes and you update the UI, you're only waiting 60 milliseconds before starting the algorithm again. It sounds like your program is spending most of its time running the algorithm. That's fine if you need it to update the screen that quickly, but you might consider using a longer delay otherwise.
Also, you're starting a new thread each time through the loop. Does that thread run the algorithm once and then terminate, or does it run the algorithm in a loop? If you have a loop starting threads that are each long-running CPU-intensive loops, you might be accidentally running many copies of the algorithm at once. If you expect the algorithm thread to terminate after it signals you, you should join() it to make sure.
How much wait do you want? If you want to wait for 60 seconds, you should use 60000L, as the time is specified in milliseconds.

Why is there no "awaitTermination(Date deadline)" method?

I have a list of tasks submitted to an ExecutorService. But I need to shutdown the ExecutorService before a deadline of 2:30AM, even if the tasks are not finished. How can I achieve this? I checked the API, there is only a method like below:
ExecutorService exec = //...
exec.awaitTermination(100, TimeUnit.MILLISECONDS);
But how can I make the following block executing atomically? That is, how can I avoid the gap? For example:
long timeDiff= calculate(now, deadline);
// Gap: assuming current thread does not have chance to run for 10 minutes...
exec.awaitTermination(timeDiff, TimeUnit.MILLISECONDS);
Thanks.
You probably don't mean 'atomically', I think you mean 'without delay' here. So that timeDiff is still correct when calling exec.awaitTermination().
I assume that's correct, so the answer is: you can't.
If you're interested in the details:
Your Java Code gets translated to Java Bytecodes and these get executed by the JVM which is a regular process running on your operating system. And you simply can't stop the operating system from interrupting threads (I assume you use a operating system with preemptive multitasking (every UNIX (including Linux and Mac OS X), Windows 95 or better, ...)).
Even if you could do all that in one Java Bytecode it would still not work as you want it to because the operating system could interrupt you in the middle of one Java Bytecode.
And even a awaitTermination(Date deadline) method wouldn't help here. It has to be implemented by someone, too.
The best you can do is to do it in as few bytecodes as possible.
If I were you, I'd probably do just as your code does it.
However, that could be a bit more precise:
Date deadline = ....;
final TimerTask stopTask = new TimerTask() {
public void run() {
exec.shutdownNow();
}
};
new Timer().schedule(stopTask, deadline);
But as I said: There is no real guarantee shotdownNow() gets executed IMMEDIATELY at deadline. In reality, setting deadline to one second before the real deadline should be okay :-)
Wait deadline in another high priority thread (or timer) and call exec.shutdownNow()

Constantly checking a port without a while loop

In a program (Java) I'm making I need to check for a specific pin in the parallel port. Whenever that pin goes from logical 0 to 1 (a positive edge clock) I have to read the data on the port and save it. This happens about every 10ms but can vary a little.
To do this I made a separate thread with a while loop that is constantly checking the port, but this makes the processor go nuts and I know it's because of the while loop. My question is, how can I constantly scan the port without using a processor intensive while loop? The program doesn't know precisely when a pin change will happen, only that it happens around every 10ms.
Fire a thread which is scheduled to execute the given Runnable at a fixed rate. You can use Timer#scheduleAtFixedRate() or ScheduledExecutorService#scheduleAtFixedRate() for this. The last one is preferred.
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new PortScanner(), 0, 10, TimeUnit.MILLISECONDS); // Run every 10 ms.
Where PortScanner can look like this:
public class PortScanner implements Runnable {
#Override
public void run() {
// Scan port here.
}
}
Don't forget to call scheduler.shutdown() at the moment your application exits, else the thread may hang.
There might be a better solution, but worst case you could just Thread.sleep for 1-2ms every iteration of the while loop.
It is really tricky to catch hardware interrupts when your code is not running as a part of operating system. What you can do is to put Thread.Sleep ( 5 ). This will sleep for 10 milliseconds, and will let the other threads run or just keep CPU idle and cool. Having 5 ms delay should be enough to ensure won't miss any clock ticks.
This would work when your clock is alternating between 10 ms high and 10 ms low. For other patterns you have to adjust the parameter accordingly.

Categories

Resources