Java: Reading and Reading/Writing to a file via multiple threads? - java

I am a newcomer to Java threads and I have a situation where I must continuously read from a file and also in a separate operation read and edit the same file(not continuously but at any random time). I understand this is a situation that can benefit from the use of multiple threads. How do I set up this situation so that both processes can take place together. I have the following code which is not thread-enabled :
Continuously reading segment(assume that readFile method has the code to read a file line-by-line):
public void init() throws ServletException
{
AlertsMonitor monitor = new AlertsMonitor();
try {
while(true)
monitor.readFile();
} catch (Exception e) {
e.printStackTrace();
}
}
And the following method may execute at any time:
public void searchUser(String user)
{
new FileSearcher().searchUser(user); //Search for the supplied string
//inside the same file
}
Both methods work on the same file. Thanks for any help !

Related

Java mp3 file errors

I am new to programming and trying to insert the mp3 file on Mac, but I have errors with these codes. I have been looking for solutions for a long time but I was not able to find the right answers. I would like to know what I did wrong.
import javazoom.jl.player.Player;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
public class Music {
public static void main(String [] args) {
String filename = "src_music_typing.mp3";
MusicPlayer music = new MusicPlayer(filename);
music.play();
}
}
class MusicPlayer {
private final String mp3File;
private Player jlPlayer;
public MusicPlayer(String mp3File) {
this.mp3File = mp3File;
}
public void play() {
try {
FileInputStream fis = new FileInputStream(mp3File);
BufferedInputStream bis = new BufferedInputStream(fis);
jlPlayer = new Player(bis);
} catch (Exception e) {
System.out.println("problem file is " + mp3File);
System.out.println(e.getMessage());
}
new Thread() {
public void run() {
try {
jlPlayer.play();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}.start();
}
public void close() {
if(jlPlayer != null) jlPlayer.close();
}
}
Problem:
problem file is src_music_typing.mp3
src_music_typing.mp3 (No such file or directory)
Cannot invoke "javazoom.jl.player.Player.play()" because "this.this$0.jlPlayer" is null
The error is telling you simply that src_music_typing.mp3 does not exist; evidently you aren't running this in the directory you think you're running it in. Trivial solution: Make that path string (String filename = "src_...") an absolute path instead.
NB: It's a cavalcade of problems, here. Your code is bad and it leads to inefficient error messages. Inefficient enough to confuse you, for example.
You should never catch an exception just to log it and then blindly continue; I know a ton of code snippets do this, but that part of them is just bad. You don't want to do that - dealing with an error by blindly continuing on is, obviously, a really silly thing to do!
The right way to deal with exceptions that you don't explicitly know how to handle is instead to just throw them on. your play method should be declared as throws IOException, as this is inherent to your API design, this is fine (it's inherent because your music player class as a property that represents a file name, and anything file related is expected to throw IOExceptions, hence, fine - not leaking an abstraction).
Then the whole try/catch bit can just go away, yay! Your code is better and shorter and easier to understand, win win win!
Because you didn't do that, and you just run blindly on, you get a second error that is complaining about attempting to invoke play() on a null pointer. This error is meaningless, in that it's merely a symptom, not the cause. The cause is the first error message. This is one of a few key reasons why 'keep blindly going' is a really bad idea - it means you get a ton of meaningless, confusing errors after the actual problem, resulting in a ton of error output, most of which is just hiding the actual problem.
If you can't throw them on, a distant second best solution is to put this in your catch blocks: throw new RuntimeException("uncaught", e);. This preserves all error information (type, message, stack trace, causal chain - all of it), and still ensures code does not blindly continue when your method is an unknown (to you) state. If you have an IDE that inserts catch blocks for you, update its template.
NB: main can and usually should be declared as static void main(String[] args) throws Exception {.

how to notify to another thread about a file being modified

I am new to the java multithreading programming. I know that it can be done by thread communication but i don't know how to proceed. I don't know how one thread would notify another if some changes are done in a file. The problem is mentioned below.
I have a comma separated file in which some lines are written. I want two threads to be started from my main thread. The csv file might be appended externally/manually. One of the thread will notify second thread if some changes are done in csv file and second thread will read that file concurrently line by line and perform some task.
Thanks.
You can use java.nio.file.WatchService for this purpose.
Refer Tutorial
From the link:-
The Watch Service API is designed for applications that need to be
notified about file change events. It is well suited for any
application, like an editor or IDE, that potentially has many open
files and needs to ensure that the files are synchronized with the
file system. It is also well suited for an application server that
watches a directory, perhaps waiting for .jsp or .jar files to drop,
in order to deploy them.
You create two thread, that inside their run method, they both use one Object as the thread wait and notify signal.
The first thread (T1), would synchronize on the object and wait on it.
The second thread (T2), would synchronize on the object, do something with it, and signal a notify.
The following snippets should give you idea... (please disregard about the endless loop and bad exception handling, its just to express the idea for ease of understanding).
public class IdeaOfThreadingWithWaitAndNotify {
public static void main(String[] args) {
File f = new File("grow.txt");
if(!f.exists()) {
try {
f.createNewFile();
Thread appenderThread = new Thread(new FileAppender(f));
Thread checkerThread = new Thread(new FileSizeCounter(f));
appenderThread.start();
checkerThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static class FileAppender implements Runnable {
private File file;
private FileOutputStream fos;
public FileAppender(File file) throws FileNotFoundException {
super();
this.file = file;
fos = new FileOutputStream(file);
}
public void run() {
while(true) {
synchronized (file) {
try {
fos.write("Appended... ".getBytes());
fos.flush();
file.notify();
Thread.sleep(1000);
} catch (IOException e) {
} catch (InterruptedException e) {
}
}
}
}
}
public static class FileSizeCounter implements Runnable {
private File file;
public FileSizeCounter(File file) {
super();
this.file = file;
}
public void run() {
while(true) {
synchronized (file) {
try {
file.wait();
} catch (InterruptedException e) {
}
System.out.println("File changed .. now size is " + file.length());
// you can do other stuff with the file...
}
}
}
}
}
there you can see, between the two thread, they are sharing the same "file" instance and use it as the wait and notify signaling. Object who call the wait will have its execution flow stop right there, until the other thread call a notify on it. Then the waiting thread can continue.
I hope this helps.

Single program instance

I need to make a program, which can be executed in single instance. I tried to create a temporary file and delete it before exit program.
public static boolean isLocked() {
File f = new File("lock.txt");
return f.exists();
}
public static void lock() {
String fname = "lock.txt";
File f = new File(fname);
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void unlock() {
File f = new File("lock.txt");
f.delete();
}
In frame
private void initialize() {
lock();
}
private void setFrameHandler() {
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
unlock();
}
});
}
Problem occurs if program is finished with emergency (e.g. electricity cuts). File does not remove, and running a new instance is impossible.
How to make a reliable single-instance verification?
You could check for another instance of the program at startup using the GetProcesses method as described here
But that only works depending on the scenario you have (might not see all processes of other users)
Another thing you could do is simply checking, if a specific file is locked via File.Open
File.Open ("path.lock", FileMode.OpenOrCreate, FileAccess.ReadWrite);
As long as you keep the resulting FileStream open in your program no other program can open the file in that mode either. This is basically how Unix lock files work too. Of course you have to catch an IOException (hinting you to a locked file).
Disclaimer: I did not try that code out so please check if I gave you the right parameters.
Edit: You could also check out this Code-Project article on how to do it with the win32 API
Another attempt using windows messaging has been done here
A simple approach to this on a single machine is to write a 'PID file', which is literally a file containing the operating system's ID of the process currently running. You create this when you start your "critical" work, and remove it on successful completion.
Since it is unlikely that the process would be started again with the same PID, you can simply check to see if the PID file already exists, and if so, if that process is still running.

Java (Android) - Synchronized Queue and sending data

I've two threads. One for generating data, second for sending them to server. Is this a classic producer-consumer situation?
To do this I've constructed simple code for managing synchronised queue - I hope: I did it more or less correct? Could somebody answer me, please? My code is here below:
public ArrayList<String> Packets;
public synchronized void add_to_Queue (String data) {
Packets.add(data);
}
public synchronized void del_from_Queue (int position) {
Packets.remove(position);
}
public synchronized String read_from_ Queue(int position) {
return Packets.get(position);
}
public synchronized int number_of_element_of_Queue() {
return Packets.size();
}
First thread add new data by putting them using simple command:
add_to_Queue("XYZ);
Second one sending data in a loop:
while (OK)
{
try
{
while (number_of_element_of_Queue()>0)
{
out.write(read_from_Queue(0)+"\n");
out.flush;
del_from_Queue(0); // if no error delete just sent element
}
}
catch (IOException e1)
{
reconnect();
}
}
I think something is wrong because sending static data (simple static text instead of reading it from my "Queue") doesn't result in reconnection (i.e. after catch (IOException e1) ). But when I use presented code, it happens very often, especially after reconnection. It does it several times (send some data, reconnect, send some more data, again reconnect and so on).
Yeah, what happens if the queue is empty? You don't seem to be checking for that or handling it. But that is not the only condition you are not accounting for.
More generally, the implementation shown is not how a Queue works. Queues are first-in-first-out, no need for a position parameter. There is not a concept of "read" then "delete", those operations are usually atomic via a "take". You are best served by using an existing BlockingQueue implementation as opposed to writing your own.

Synchronisation on java.io.File Object

Is it good to use synchronised on java.io.File Object. When you want to alternatively read and write that File Object using two threads: one for reading and one for writing.
public class PrintChar {
File fileObj;
public void read() {
while (true) {
synchronized (this) {
readFile();
notifyAll();
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " throws Exception");
e.printStackTrace();
}
}
}
}
public void write(String temp) {
while (true) {
synchronized (this) {
writeFile(temp);
notifyAll();
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " throws Exception");
e.printStackTrace();
}
}
}
}
public void setFileObj(File fileObj) {
this.fileObj = fileObj;
}
public void readFile() {
InputStream inputStream;
try {
inputStream = new FileInputStream(fileObj);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(inputStream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println(strLine);
}
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile(String temp) {
BufferedWriter bw;
try {
bw = new BufferedWriter(new FileWriter(fileObj, true));
bw.write(temp);
bw.newLine();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
final PrintChar p = new PrintChar();
p.setFileObj(new File("C:\\sunny.txt"));
Thread readingThread = new Thread(new Runnable() {
#Override
public void run() {
p.read();
}
});
Thread writingThread = new Thread(new Runnable() {
#Override
public void run() {
p.write("hello");
}
});
Thread Randomizer = new Thread(new Runnable() {
#Override
public void run() {
while (true)
try {
Thread.sleep(500000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " throws Exception");
e.printStackTrace();
}
}
});
readingThread.start();
writingThread.start();
Randomizer.start();
}
}
In the code above I have used Synchronised(this), Can i use Synchronise(fileObj)??
One More solution I have got from one of my professors is to encapsulate the read and write in objects and push them in a fifo after every operation, if anybody elaborate on this
Edit:
Now that you have added your code, you can lock on fileObj but only if it is not changed. I would move it to the constructor and make it final to make sure that someone doesn't call setFileObj inappropriately. Either that or throw an exception if this.fileObj is not null.
Couple other comments:
Don't use notifyAll() unless you really need to notify multiple threads.
If you catch InterruptedException, I'd quit the thread instead of looping. Always make good decisions around catching InterruptedException and don't just print and loop.
Your in.close(); should be in a finally block.
You can lock on any object you want as long as both threads are locking on the same constant object. It is typical to use a private final object for example:
private final File sharedFile = new File(...);
// reader
synchronized (sharedFile) {
// read from file
}
...
// writer
synchronized (sharedFile) {
// write to file
}
What you can't do is lock on two different File objects, even if they both point to the same file. The following will not work for example:
private static final String SHARED_FILE_NAME = "/tmp/some-file";
// reader
File readFile = new File(SHARED_FILE_NAME);
synchronized (readFile) {
...
}
// writer
File writeFile = new File(SHARED_FILE_NAME);
synchronized (writeFile) {
...
}
Also, just because you are locking on the same File object does not mean that the reading and writing code will work between the threads. You will need to make sure that in the writer that all updates are flushed in the synchronized block. In the reader you probably do not want to use buffered streams otherwise you will have stale data.
In general, locking across I/O is not a great idea. It's better to construct your program such that you guarantee by design that usually a given section of the file is not being concurrently written and read, and only lock if you absolutely must mediate between reads and writes of a given piece of the file.
Usually not. There are much better ways: Use a ReentrantLock
This class already offers the "lock for reading/writing" metaphor. It also correctly handles the case that many threads can read at the same time but only one thread can write.
As other people already mentioned, locking will only work if all threads use the same File instance.
Make sure you flush the output buffers after each write; this will cost some performance but otherwise, you'll get stale reads (read thread won't find data that you expect to be there).
If you want to simplify the code, add a third thread which accepts commands from the other two. The commands are READ and WRITE. Put the commands in a queue and let the 3rd thread wait for entries in the queue. Each command should have a callback method (like success()) which the 3rd thread will call when the command has been executed.
This way, you don't need any locking at all. The code for each thread will be much more simple and easy to test.
[EDIT] Answer based on your code: It would work in your case because everyone uses the same instance of fileObj but it would mix several things into one field. People reading your code would expect the file object to be just the path to the file to read. So the solution would violate the principle of least astonishment.
If you'd argue that it would save memory, then I'd reply with "premature optimization".
Try to find a solution which clearly communicates your intent. "Clever" coding is good for your ego but that's about the only positive thing that one can say about it (and it's not good for your ego to learn what people will say about you after they see your "clever" code for the first time...) ;-)
Queueing off read/write objects to one thread that then performs the operation is a valid approach to something, but I'm not sure what.
Wha it would not do, for example, is to enforce read/write/read/write order as you specified in your earlier question. There is nothing to stop the read thread queueing up 100 read requests.
That could be prevented by making the thread that submits an object wait on it until it is signaled by the read/write thread, but this seems a very complex way of just enforcing read/write order, (assuming that's what you still want).
I'm getting to the state now where I'm not sure what it is you need/want.

Categories