Process A writes in a file XYZ, when executed. There are processes B and C, which when executed, reads the file XYZ. So, while process A is up, B and C should wait for A to complete. To provide synchronization can I use java.nio package? or I should use something like FileLock or sockets? Can we mention the time to wait for the second process to wait?
Edited: The file is created during the first write process. In such case, can I make it shared resource?
Using java.nio package's file lock could be a better solution, I hope. But, I think java.nio is not full-fledged till JDK 1.6.
http://www.withoutbook.com/DifferenceBetweenSubjects.php?subId1=7&subId2=43&d=Java%206%20vs%20Java%207
FileLock:
http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileLock.html
One way could be the usage of a flag. Just a boolean stillWriting which is readable from outside.
As soon process A did its Job, this flag is set to false and your processes B/C can start their work with this file.
Assuming A wants to start again editing this file, it'll set this flag back to true and block the other two processes.
Using locks would be a good idea. You can use Conditions from JavaAPi.
Refer to [http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#awaitNanos(long)][1]
When A is working it should signal the thread to await and then on completion it can signal so that other thread waiting to start can proceed. Also this is very appropriate when we use shared resource.
Related
I have two Java processes and need to make sure that they do not simultaneously access directory /dir. I am not sure how to properly implement this behaviour.
My idea would be to define a certain file lock.txt and do something like
if not (lock.txt exists)
{
create lock.txt with content "process 1"
do something in /dir
delete lock.txt
}
But I guess I could run into some kind of race condition if both processes check this simultaneously.
EDIT: my Java processes are separate programs.
Look at the FileLock class here: http://docs.oracle.com/javase/6/docs/api/java/nio/channels/FileLock.html
You could have found this with a bit of googling
I have a multi-threaded Java 7 program (a jar file) which uses JDBC to perform work (it uses a fixed thread pool).
The program works fine and it logs things as it progresses to the command shell console window (System.out.printf()) from multiple concurrent threads.
In addition to the console output I also need to add the ability for this program to write to a single plain ASCII text log file - from multiple threads.
The volume of output is low, the file will be relatively small as its a log file, not a data file.
Can you please suggest a good and relatively simple design/approach to get this done using Java 7 features (I dont have Java 8 yet)?
Any code samples would also be appreciated.
thank you very much
EDIT:
I forgot to add: in Java 7 using Files.newOutputStream() static factory method is stated to be thread safe - according to official Java documentation. Is this the simplest option to write a single shared text log file from multiple threads?
If you want to log output, why not use a logging library, like e.g. log4j2? This will allow you to tailor your log to your specific needs, and can log without synchronizing your threads on stdout (you know that running System.out.print involves locking on System.out?)
Edit: For the latter, if the things you log are thread-safe, and you are OK with adding LMAX' disruptor.jar to your build, you can configure async loggers (just add "async") that will have a logging thread take care of the whole message formatting and writing (and keeping your log messages in order) while allowing your threads to run on without a hitch.
Given that you've said the volume of output is low, the simplest option would probably be to just write a thread-safe writer which uses synchronization to make sure that only one thread can actually write to the file at a time.
If you don't want threads to block each other, you could have a single thread dedicated to the writing, using a BlockingQueue - threads add write jobs (in whatever form they need to - probably just as strings) to the queue, and the single thread takes the values off the queue and writes them to the file.
Either way, it would be worth abstracting out the details behind a class dedicated for this purpose (ideally implementing an interface for testability and flexibility reasons). That way you can change the actual underlying implementation later on - for example, starting off with the synchronized approach and moving to the producer/consumer queue later if you need to.
Keep a common PrintStream reference where you'll write to (instead of System.out) and set it to System.out or channel it through to a FileOutputStream depending on what you want.
Your code won't change much (barely at all) and PrintStream is already synchronized too.
Are methods Files.createFile() and Files.delete() thread safe? I have read in documentation that createFile() always an atomic operation but delete() is not. Should I somehow synchronize these blocks in my Java application and how? What atomic operation means for multihreading task?
a. What atomic operation means for multihreading task?
In context of multi-threading atomicity is the ability of a thread to execute a task in such a manner so that other threads have apparently no side-effect over the state varibles of that task when it was being executed by this thread.
File.createNewFile() :- For this method the state is existence or non existence of the file, when the thread was about to execute this method. Lets say that when this method was being executed by the thread the file did not exist. Now lets say that this method takes 5 ms of time to execute and create the file. So according to the concept of Atomicity no other thread should be able to create the same file(which was not existing before) during these 5ms otherwise the very first assumption of this thread about the state of the file will change and hence the output.
So in this case the executing thread does-this by obtaining a write lock over the directory where file is to be created.
Files.delete():- The Java doc for this method says
this method may not be atomic with respect to
other file system operations. If the file is a symbolic link, then the
symbolic link itself, not the final target of the link, is deleted.
the above statement says that this operation is also atomic but in case if this method is invoked on a symbolic link, the link is deleted and not the file. Which implies that the original file exists and file system operations on that file are feasible by other threads.
to determine if a file is a symlink see the reference:-
determine symlink
b. Should I somehow synchronize these blocks in my Java application and how?
You need not handle any multi-threading scenarios in both the cases.
However you can use the method mentioned in the link above to determine symlinks and handle that separately as you would wish.
But no synchronization is required from your end for sure.
Do you mean File.createNewFile()?
Javadoc says:
The check for the existence of the file and the creation of the file if it does not exist are a single operation that is atomic with respect to all other filesystem activities that might affect the file.
With other words, between the check if the file exist and the creation of the file will be no other file operation, changing the existence of the file.
If two threads want to create the same non existing file, only one will create the file and return true. The other thread will return false.
Usually you dont need to synchronize these operations but do a proper exception handling. Maybe other programs operate on your files too.
Suppose a Java application writes to a file using BufferedWriter API (and does not call flush after every write). I guess that if the application exits with System.exit the buffer is not flushed and so the file might be corrupted.
Suppose also that the application component, which decides to exit, is not aware of the component, which writes to the file.
What is the easiest and correct way to solve the "flush problem" ?
You may use the Runtime.addShutdownHook method, which can be used to add a jvm shutdown hook. This is basically a unstarted Thread, which executes on shutdown of the Java Virtual Machine.
So if you have a handle of the file available for that thread, then you can try to close the stream and flush the output.
Note: Although it seems feasible to use this, but I believe there will be implementation challenges to it because of the fact that whether your file handle is not stale when your shutdown hook is called. So the better approach should be to close your streams gracefully using finally blocks in the code where file operations are done.
You can add a shutdown hook but you need to have a reference to each of these BufferedWriter or other Flushable or Closable objects. You won't gain anything from it. You should perform close() and flush() directly in the code that is manipulating the object.
Think of the Information Expert GRASP pattern, the code manipulating the BufferedWriter is the place that has the information about when an operation is finished and should be flushed, so that's where that logic should go.
If some application component is calling System.exit when things aren't done, I would consider that an abnormal exit, should not return 0 and therefore shouldn't guarantee that streams are flushed.
I have three services in my Android app that are fired by two broadcast receivers. The first two write onto a file and are fired by one broadcast receiver so I can make sure that they are executed one after the other (via Context.sendOrderedBroadcast()). The third one is on its own and is fired by a separate broadcast receiver, but reads from the same file that the first two write on.
Because the broadcast receivers may be fired at the same time or nearly the same time as each other, the file might also be accessed concurrently. How can I prevent that from happening? I want to be able to either read first then write or write then read. I'm just not sure if this problem is similar to Java concurrency in general because android services, if I'm not mistaken, are an entirely different beast.
One solution would be to have your writing tasks create an empty temporary file (say .lock) before accessing the shared file and delete that same temporary file once they are done.
Your reading task can check whether .lock file exists or not.
Alternatively, you can use a FileLock.
http://developer.android.com/reference/android/app/Service.html
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work.
I suggest to read from/write to file in separate thread. You can use Only one thread at a time! for doing it in the same thread.
First of all, I shouldn't have done the file I/O in the main UI thread which is the case with Services. It should be done in another thread, like an AsyncTask.
Secondly, the ReentrantLock method is so much easier. When locked, it tells the other threads accessing the same resource to wait, and proceed only when the lock has been released. Simply instantiate a new ReentrantLock() and share that lock among the methods that read to or write from the file. It's as easy as calling lock() and unlock() on the ReentrantLock as you need it.