I have a Java program that writes to a file whenever a user does a certain action. To avoid blocking the main thread I thought it would be best to handle writing to that file on a separate thread. Anyways I am wondering what's the best way to go about that. At first I created a new object that implements Runnable. Then when ever I needed to write to a file I created a new instance of that object and a new thread, passed in the runnable as a parameter to the thread and started it. This works fine however I was not sure if this was the best approach and based on my research apparently creating a new thread object is very memory intensive.
final UpdateConfigRunnable runnable = new UpdateConfigRunnable(stringData, object);
final Thread thread = new Thread(runnable);
thread.start();
Normally I was passing in an object (all data being queried from that object is final) and some string data into the constructor of my runnable object. One issue is I cant generate a new runnable and pass it into the same thread which means I need to make the thread once and the runnable once then maybe update stringData with a setter method before I call the start method? That implantation would look like this.
public class NormalClass {
final UpdateConfigRunnable runnable;
final Thread thread;
public NormalClass(Object object) {
runnable = new UpdateConfigRunnable(object);
this.thread = new Thread(runnable);
}
public void updateFile(String data) {
runnable.setData(data);
thread.start();
}
}
In the above implementation "NormalClass" is only ever accessed / called by one single thread. Calling the updateFile() method would then change the value of stringData inside the runnable object before I start the thread with the start() method. Is this the second example the correct way to go about this if not what did I get wrong about using multiple threads in this scenario?
CodePudding user response:
Use one thread that keeps reading from a BlockingQueue and writing to the file. If there is nothing to write, the thread gets blocked by the BlockingQueue.take() method.
Now all your other threads have to do is to add data via the BlockingQueue.add() method.
CodePudding user response:
Juste replace old thread with a new Thread inside updateFile and for each call, interrupt and cancel all changes of the old thread and replace it with a new one, with previous data that you canceled, to save it in the file with the new data you want to store for the current function call
I did a small implementation :
public class HelloWorld {
public volatile String oldFileData = "";// use volatile
private Thread activeThread ;
public HelloWorld(String init) {
//inside the constructor read all the current file content iven if it's blocking because it will be done once and will be usefull for ever
this.oldFileData = init;
}
public void updateLogFile(String toPrint){
if(activeThread!=null && activeThread.isAlive()) {
activeThread.interrupt();
//write in append mode
this.activeThread = new Thread(() -> {
// append to the file
oldFileData = toPrint;
});
activeThread.start();
}else{
//replace all content in write mode
this.activeThread = new Thread(() -> {
// replace all in that file with oldFileData
oldFileData = toPrint;
});
activeThread.start();
}
}
public static void main(String[] args) {
HelloWorld hw = new HelloWorld("I m old content from the file");
hw.updateLogFile("User clicked button1 ");
hw.updateLogFile("User clicked button2 ");
System.out.println(hw.oldFileData);
}
}