Java - Thread.sleep in main method

I am looking at Java code, which is essentially a repeating process that moves / reads / parses some files on a regular basis and dumps data into a database. The repeating part is performed (approximately) as follows:

public class CollectorMain { public static boolean signalRecieved = false; public static void main(String[] args) { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { shutdown(); }}); while(!signalRecieved) { Collector.execute(); try { Thread.sleep(60 * 1000); } catch (InterruptedException e) { break; } } // some shutdown logic } public static void shutdown() { signalReceived = true; } } public class Collector() { public static void execute() { // Move files from the queue dir to temp location // Read, parse files and insert records into database. // Then delete the processed files } } 

My recommendation was that the refactoring code be

  • Create an instance of the static method of the Collector method and refactor static () for the instance method
  • Use Runnable or TimerTask to handle calls

My argument was that using Thread.wait from the main method and combining it with static access is not a good way to handle a repeatable process, especially making an IO file. To which the author replied (cited)

The Runnable description says: "must be implemented by any class whose instances are intended to be executed by the thread." In fact, I intentionally avoid threads in this program for cost reasons vrs.performance requirements.

Here is another quote from the same discussion, which we hope will help clarify the author’s position

Technically, Java is not executed at all, it is interpreted by the JVM which then executes machine instructions to simulate that Java code is executed. So this is really a JVM that runs on a thread or multiple threads.

But as a Java code writer, I don't care. If I do not create “threads” in Java, then it is the JVM’s task to look like there are no threads — even if the JVM uses threads “under the covers”.

Java pause is not executed; it is modeled by a sequence of machine instructions that may or may not cause the OS to wait. (Probably because the JVM will not want to spin, burning processor cycles, but this is the choice of the JVM implementation).

I have 2 questions:

  • Does Thread.wait insert a legitimate, safe, and appropriate way to perform the repetitive task in the main method in this case? And if not, then why not, since there is only one (main) thread of execution?
  • What are the scenarios for using static methods in this context (if any)?

I will be happy to provide additional information if you have other questions.

+6
source share
4 answers

You really discuss design decisions, not performance decisions.

Your colleague's expression on how Thread.sleep is implemented is basically incorrect, as far as I can tell. On a smart JVM in a smart operating system, Thread.sleep () is implemented using its own O / S method to park the thread (or put it in a "timeout" state or whatever you want to call it on your OS), or to another, while the thread is sleeping, it consumes a zero processor. And in any case, TimerTask will use Thread.sleep (or similar - I don't just remember if it uses the park () method introduced in Java 5, but it doesn't really matter).

The JVM generally does not make secret decisions about ceiling processing. If you ask for another thread, you will get it; if you do not, you will not. For garbage collection, etc. Several home streams will be created, but as far as your code is concerned, you can assume that no covert clever creation of streams occurs.

So, back to your questions:

  • sleeping in the main thread is completely safe; Obviously, while the main thread was sleeping, it will not do anything, but if you do not need it, then this is fine;
  • regardless of whether you use Thread.sleep () directly in your code or use one of the timer utility methods, this is again a design decision based on whether you want to use a shared library that removes the resulting data from your code , or you prefer to have these details under your control; in terms of performance, this will have little chance if you implement things correctly;
  • Do you have a static method or do you have an instance of Collector, this is not a fundamental decision - it is just a design decision that needs to be made on the basis of what seems more intuitive: you see Collector as a class of “general utility”, or as a “thing” with the state that you request to perform operations?
+6
source

You are misleading sleep and wait . sleep makes the current thread idle for a period of time, and then the thread restarts on its own. wait is an object method. He used to put the thread on hold, and it will only exit this state if another thread notify it using notify or notifyAll on the same object. Using wait , if only one executable thread just makes your program exist forever.

Read http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html

+3
source

I think your colleague does not really understand the JVM and its threading model; your code will not be magically multithreaded unless you explicitly do it that way. Also, I think both of you are working too hard on this. Ask the Quartz library to try: http://quartz-scheduler.org/documentation/quartz-2.1.x/quick-start

My reasoning is that Java Threading is hard to get right, especially when you find yourself doing wait / notify on your own and fighting all the extreme cases. The quartz library completely discarded all this and put a repeating aspect behind the familiar CRON pattern.

I would completely avoid TimerTask since it has the unpleasant habit of silently crashing if there are any unhandled exceptions that occur during your run.

Calling static methods or not - it doesn’t matter, regardless of your decision, the key understands which state gets shared by threads and either removes shared access or synchronizes access to it, so all threads get a consistent view of the data. If I were you, I would give Quartz a shot. If you are reluctant to add another library, JDK 1.5 (I think) brought in a ScheduledExectutorService, which, I think, performs repetitive tasks.

Regardless of which direction you are going, do not write your own planning / planning structure. This is a solvable problem in Quartz or ScheduledExectutorService.

+1
source

In the presented code example, I would use Object.wait(60 * 1000) instead of Thread.sleep(60 * 1000) , then in the shutdown method add a call to notifyAll() after setting signalReceived = true . This will require the addition of the necessary synchronization blocks around the notification and wait methods. At a minimum, this will provide the advantage of a “wait loop” that allows you to exit immediately, rather than waiting for the timeout to finish first. (See JB Nizet for more information on this.)

From a general point of view - I will have a TimerTask collector ( Runnable sub-interface), mark it as a Timer and do it with it.

Some users will favor the use of static for performance reasons, which, in my opinion, will be mostly historical. Saving all non-static will allow you to use several instances within the same JVM in the future, as well as the ability to use subclasses to override methods and configure the base implementation.

0
source

Source: https://habr.com/ru/post/904561/


All Articles