Last time, I wrote an article Log output to file with Java. Therefore, I wrote that it seems that exclusive control can be performed on the log file by changing the log output method to the syncronized method, so I would like to verify it this time.
Execute 10 threads that call the log output method 10000 times in parallel, and check if the log specified by each thread is completely output to the log file.
As for threads, there are various samples, so no explanation is necessary. The log output method has been moved to the writeLog method of the LogWriter class so that it can be called from various threads.
LogWriterTest.java
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;
import java.io.*;
public class LogWriterTest{
public static void main(String[] argv){
ThreadSample[] threadSamples = new ThreadSample[10];
//Thread preparation
for (int i = 0; i < threadSamples.length; i++) {
threadSamples[i] = new ThreadSample("Trhead[" + i + "]");
}
//Start thread
for (int i = 0; i < threadSamples.length; i++) {
threadSamples[i].start();
}
}
}
//Log output class
class LogWriter {
public static SimpleDateFormat sdf = new SimpleDateFormat("YYYY/MM/dd HH:mm:ss");
//Log output method
public static synchronized void writeLog(String text) {
Calendar calendar = Calendar.getInstance();
String OUTPUT_DIR = "out";
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
Date date = calendar.getTime();
String yearStr = String.format("%04d", year);
String monthStr = String.format("%02d", month);
//Log output
String file_name = OUTPUT_DIR + File.separator + yearStr + "_" + monthStr + ".log";
File file = new File(file_name);
FileWriter fw = null;
String line = sdf.format(date) + "," + text;
try {
fw = new FileWriter(file, true);
fw.write(line + "\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try {
fw.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
}
class ThreadSample extends Thread {
//Thread name
private String name = null;
public ThreadSample(String name) {
this.name = name;
}
//Thread that writes 10000 lines to the log
public void run() {
for (int i = 0; i < 10000; i++) {
System.out.println(name + "," + i);
LogWriter.writeLog(name + "," + i + ":hogehoge");
}
}
}
The contents of the file shouldn't be corrupted like this. You can also see that the logs of various threads are output to a file in parallel.
2020/05/23 09:48:59,Trhead[2],0:hogehoge
2020/05/23 09:48:59,Trhead[5],0:hogehoge
2020/05/23 09:48:59,Trhead[6],0:hogehoge
2020/05/23 09:48:59,Trhead[9],0:hogehoge
2020/05/23 09:48:59,Trhead[0],0:hogehoge
2020/05/23 09:48:59,Trhead[7],0:hogehoge
2020/05/23 09:48:59,Trhead[8],0:hogehoge
2020/05/23 09:48:59,Trhead[3],0:hogehoge
2020/05/23 09:48:59,Trhead[1],0:hogehoge
2020/05/23 09:48:59,Trhead[4],0:hogehoge
2020/05/23 09:48:59,Trhead[1],1:hogehoge
2020/05/23 09:48:59,Trhead[3],1:hogehoge
2020/05/23 09:48:59,Trhead[8],1:hogehoge
2020/05/23 09:48:59,Trhead[7],1:hogehoge
2020/05/23 09:48:59,Trhead[0],1:hogehoge
2020/05/23 09:48:59,Trhead[9],1:hogehoge
2020/05/23 09:48:59,Trhead[6],1:hogehoge
2020/05/23 09:48:59,Trhead[5],1:hogehoge
2020/05/23 09:48:59,Trhead[2],1:hogehoge
2020/05/23 09:48:59,Trhead[5],2:hogehoge
2020/05/23 09:48:59,Trhead[6],2:hogehoge
The number of cases was 10,000 for each thread, for a total of 100,000, and it was confirmed that all the threads were output.
$ grep 'Trhead\[0\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[1\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[2\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[3\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[4\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[5\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[6\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[7\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[8\]' 2020_05.log |wc -l
10000
$ grep 'Trhead\[9\]' 2020_05.log |wc -l
10000
$ wc -l 2020_05.log
100000 2020_05.log
I'll output a pounding log using this method!
By the way, even without syncronized, the log was output without exception in a small job environment. The processing was also overwhelmingly fast. However, it can be a coincidence, so it is better to add syncronized at the expense of processing time.
In a small program, date processing and file name determination are performed in the synchronized method, but if you move this to the caller and shorten the synchronization processing time, it may be a little faster (not yet). Experiment).
Recommended Posts