Thread.sleep() / robot.delay() more accurate? - java

I want to write a bot for a online game using the Robot class. My problem is now, that the method Thread.sleep() or robot.delay() is to inaccurate. Outside the game they work perfectly fine, with a deviation of approximately only 2 - 3 ms. But when the game is in focus, the methods have a deviation of +5 - +20 ms or even more. That is sadly enaugh to make my bot unusable. Is there any way to make these methods more accurate? Or are there any other ways to solve this problem?

There is no difference
If you browse the source for the JDK, Robot.delay() ends up calling Thread.sleep().
public void delay(int ms) {
checkDelayArgument(ms);
Thread thread = Thread.currentThread();
if (!thread.isInterrupted()) {
try {
Thread.sleep(ms);
} catch (final InterruptedException ignored) {
thread.interrupt(); // Preserve interrupt status
}
}
}
You might be able to give the Java process a higher priority then the game, tasks might be executed more quickly after being given to the scheduler.

Related

Changing the while loops condition in another thread, nothing happens? [duplicate]

This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
So, the other day I made a fractal drawing program, and when it got too slow, I thought I would make it a bit faster by multithreading it. So I introduced a couple of threads to each draw a portion of the image. To know when I was done with the threads, I introduced two variables, AMOUNT_OF_THREADS and threadsDone. I created AMOUNT_OF_THREADS threads, that each drew their own partition and increased threadsDone when done. In the main method, I put in
while (threadsDone < AMOUNT_OF_THREADS)
;
It surprised me that that loop never finished looping. I knew it because each thread printed out "Thread done" and when the main method loop was done it should have printed out "Main done" but it didn't. I tried to print out threadsDone < AMOUNT_OF_THREADS and now the loop stopped. Weird.
I did some further testing and this problem seems only to occur if the thread takes >2ms to run or the loop takes >2ms each time it loops. Sometimes this bug occurs when the thread takes 2ms to run.
I suspect that the print function made the loop take >2ms to run and that made it work when I printed out the value, but I still wonder why this happens.
So my question is, why does this happen? Is it a bug in the compiler/JVM, or anything else? I asked my dad, and he replied after thinking for a few minutes that it has to be the while loop running too fast, but he wasn't sure.
Here's a little example of some code that has this problem:
public class WhileThread {
public static boolean threadDone = false;
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadDone = true;
System.out.println("Thread done.");
}
}).start();
while (!threadDone) {
}
System.out.println("Main program done.");
}
}
When you change the 0 in the Thread.sleep into a 10, this bug never happens.
If it matters, I use a Macbook Air with Java SE 8.
So my question is, why does this happen? Is it a bug in the compiler/JVM, or anything else?
It's not a bug, it's a deliberate design decision. To make code like this work reliably, JVMs would have to assume that any thread could change any variable at any time unless they could prove that this couldn't happen. This would inhibit all kinds of extremely valuable optimizations and make Java code run much more slowly.
So instead, these optimizations were explicitly allowed and several methods (volatile, synchronized, and so on) were added to allow coders to show where variables could have their values changed by other threads.

How do I make my system wait 5 seconds before continuing?

I'm currently working on a Black Jack game in a school project. When the machine rolls, I want to make it wait 5 seconds each time it rolls to make it more exciting. How do I do this?
Use Thread#sleep():
Thread.sleep(5000);
The method can throw InterruptedException if any thread has interrupted the current thread. Usually you would catch the exception and handle it but if your program is single threaded, you don't need to worry about it. So you can just specify that the method calling Thread.sleep throws an InterruptedException:
public void foo() throws InterruptedException {
...
Thread.sleep();
...
}
You can use threading to sleep 5 seconds your current thread
try {
Thread.sleep(5000); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
I Think this will help you :)
It can be done using the Thread Class with method sleep
Java Docs Says :
sleep(long millis);
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers.
Example:-
Thread.sleep(5000);
I guess you should you use a very large loop repetition in any programming language to create a delay.

How do I reduce/change delay after crawling?

Has anybody experience with using Crawler4j?
I followed the example from the project page to realize my own crawler. The crawler is working fine and crawls very fast. The only thing is that I always have a delay of 20–30 seconds. Is there a way to avoid the waiting time?
Just checked crawler4j source code. The CrawerController.start method have a lot of fixed 10 seconds "pauses" going on to make sure that threads are done and ready to be cleaned up.
// Make sure again that none of the threads
// are
// alive.
logger.info("It looks like no thread is working, waiting for 10 seconds to make sure...");
sleep(10);
// ... more code ...
logger.info("No thread is working and no more URLs are in queue waiting for another 10 seconds to make sure...");
sleep(10);
// ... more code ...
logger.info("Waiting for 10 seconds before final clean up...");
sleep(10);
Also, the main loop checks every 10 seconds to know if the crawling threads are done:
while (true) {
sleep(10);
// code to check if some thread is still working
}
protected void sleep(int seconds) {
try {
Thread.sleep(seconds * 1000);
} catch (Exception ignored) {
}
}
So it may be worth to fine tune those calls and reduce the sleeping time.
A better solution, if you can spare some time, would be to rewrite this method. I would replace the List<Thread> threads by an ExecutorService, its awaitTermination method would be particularly handy. Unlike Sleep, awaitTermination(10, TimeUnit.SECONDS) will return immediately if all tasks are done.

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.

How could I make a thread loop?

Every 3 seconds, I want the server to send a message.
To do this, I have this code.
try {
Thread.sleep(3500);
getPackets().sendGameMessage("[Server Message]: Remember to vote!");
} catch (InterruptedException e) {
e.printStackTrace();
}
The code works of course, waits 3 and a half seconds, sends the message.
But how can I make it loop, so every 3 and a half seconds, it will send it without stopping?
I'm a bit surprised that someone tackling networking in Java doesn't know how to put code in an infinite loop. Thus, I wonder if your real question is "is there a better way?"
To that question, I would say that you should consider using either java.util.Timer to send the message, or using scheduleAtFixedRate() from a ScheduledExecutorService obtained from Executors.newScheduledThreadPool().
The best way is to use a Timer. See Java how to write a timer
spawn the above code in a separate thread and enclose it within a while(true) loop.
This kind of code is not very useful because it blocks the current thread and also seems to unnecessarily clutter the program logic. It's better to delegate it to a worker thread that executes the send in the background. Also Thread.sleep is known to be inaccurate.
As of the latest Java versions, I think the most elegant way to do it is using ScheduledThreadPoolExecutor:
ScheduledThreadPoolExecutor executor = new ScheduledThraedPoolExecutor(1);
executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
getPackets().sendGameMessage("[Server Message]: Remember to vote!");
}
}, 0, 3500, TimeUnit.MILLISECONDS);
Also you don't have to worry about that annoying InterruptedException.

Categories

Resources