I'm testing processing of a large file (10.000.100 rows) with java.
I wrote a piece of code which reads from the file and spawns a specified number of Threads (at most equal to the cores of the CPU) which, then, print the content of the rows of the file to the standard output.
The Main
class is like the following:
public class Main
{
public static void main(String[] args)
{
int maxThread;
ArrayList<String> linesForWorker = new ArrayList<String>();
if ("MAX".equals(args[1]))
maxThread = Runtime.getRuntime().availableProcessors();
else
maxThread = Integer.parseInt(args[1]);
ExecutorService executor = Executors.newFixedThreadPool(maxThread);
String readLine;
Thread.sleep(1000L);
long startTime = System.nanoTime();
BufferedReader br = new BufferedReader(new FileReader(args[0]));
do
{
readLine= br.readLine();
if ("X".equals(readLine))
{
executor.execute(new WorkerThread((ArrayList) linesForWorker.clone()));
linesForWorker.clear(); // Wrote to avoid storing a list with ALL the lines of the file in memory
}
else
{
linesForWorker.add(readLine);
}
}
while (readLine!= null);
executor.shutdown();
br.close();
if (executor.awaitTermination(1L, TimeUnit.HOURS))
System.out.println("END\n\n");
long endTime = System.nanoTime();
long durationInNano = endTime - startTime;
System.out.println("Duration in hours:" + TimeUnit.NANOSECONDS.toHours(durationInNano));
System.out.println("Duration in minutes:" + TimeUnit.NANOSECONDS.toMinutes(durationInNano));
System.out.println("Duration in seconds:" + TimeUnit.NANOSECONDS.toSeconds(durationInNano));
System.out.println("Duration in milliseconds:" + TimeUnit.NANOSECONDS.toMillis(durationInNano));
}
}
And then the WorkerThread
class is structured as following:
class WorkerThread implements Runnable
{
private List<String> linesToPrint;
public WorkerThread(List<String> linesToPrint) { this.linesToPrint = linesToPrint; }
public void run()
{
for (String lineToPrint : this.linesToPrint)
{
System.out.println(String.valueOf(Thread.currentThread().getName()) + ": " + lineToPrint);
}
this.linesToPrint = null; // Wrote to help garbage collector know I don't need the object anymore
}
}
I run the application specifing 1 and "MAX" (i.e. number of CPUs core, which is 4 in my case) as the maximum thread of the FixedThreadPool and I experienced:
- An execution time of about 40 minutes when executing the application with 1 single thread in the
FixedThreadPool
. - An execution time of about 44 minutes when executing the application with 4 threads in the
FixedThreadPool
.
Someone could explain me this strange (at least for me) behaviour? Why multithreading didn't help here?
P.S. I have SSD on my machine
EDIT: I modified the code so that the Threads now create a file and write their set of lines to that file in the SSD. Now the execution time has diminished to about 5 s, but I still have that the 1-thread version of the program runs in about 5292 ms, while the multithreaded (4 threads) version runs in about 5773 ms.
Why the multithreaded version still lasts more? Maybe every thread, even to write his "personal" file, has to wait the other threads to release the SSD resource in order to access it and write?