for the task at school, I was asked to create a simple program that creates 1000 text files, each with a random number of lines, counts how many lines exist through a multi-threaded \ single process. than delete these files.
now a strange thing happens during testing - linear counting of all files is always a little faster than counting them in multithreaded mode, which caused a rather academic theorizing session in my class.
when using Scanner to read all files everything works as intended - 1000 files are read with a linear time of 500 ms and a scroll time of 400 ms
but when I use BufferedReader times, the drop is about 110 ms in a linear and 130 ms stream.
what part of the code causes this bottleneck and why?
EDIT: just for clarification, I am not asking why Scanner is slower than BufferedReader .
full compiled code: (although you should change the output of the file creation path)
import java.io.*; import java.util.Random; import java.util.Scanner; /** * Builds text files with random amount of lines and counts them with * one process or multi-threading. * @author Hazir */// CLASS MATALA_4A START: public class Matala_4A { /* Finals: */ private static final String MSG = "Hello World"; /* Privates: */ private static int count; private static Random rand; /* Private Methods: */ /** * Increases the random generator. * @return The new random value. */ private static synchronized int getRand() { return rand.nextInt(1000); } /** * Increments the lines-read counter by a value. * @param val The amount to be incremented by. */ private static synchronized void incrementCount(int val) { count+=val; } /** * Sets lines-read counter to 0 and Initializes random generator * by the seed - 123. */ private static void Initialize() { count=0; rand = new Random(123); } /* Public Methods: */ /** * Creates n files with random amount of lines. * @param n The amount of files to be created. * @return String array with all the file paths. */ public static String[] createFiles(int n) { String[] array = new String[n]; for (int i=0; i<n; i++) { array[i] = String.format("C:\\Files\\File_%d.txt", i+1); try ( // Try with Resources: FileWriter fw = new FileWriter(array[i]); PrintWriter pw = new PrintWriter(fw); ) { int numLines = getRand(); for (int j=0; j<numLines; j++) pw.println(MSG); } catch (IOException ex) { System.err.println(String.format("Failed Writing to file: %s", array[i])); } } return array; } /** * Deletes all the files who file paths are specified * in the fileNames array. * @param fileNames The files to be deleted. */ public static void deleteFiles(String[] fileNames) { for (String fileName : fileNames) { File file = new File(fileName); if (file.exists()) { file.delete(); } } } /** * Creates numFiles amount of files.<br> * Counts how many lines are in all the files via Multi-threading.<br> * Deletes all the files when finished. * @param numFiles The amount of files to be created. */ public static void countLinesThread(int numFiles) { Initialize(); /* Create Files */ String[] fileNames = createFiles(numFiles); Thread[] running = new Thread[numFiles]; int k=0; long start = System.currentTimeMillis(); /* Start all threads */ for (String fileName : fileNames) { LineCounter thread = new LineCounter(fileName); running[k++] = thread; thread.start(); } /* Join all threads */ for (Thread thread : running) { try { thread.join(); } catch (InterruptedException e) { // Shouldn't happen. } } long end = System.currentTimeMillis(); System.out.println(String.format("threads time = %d ms, lines = %d", end-start,count)); /* Delete all files */ deleteFiles(fileNames); } @SuppressWarnings("CallToThreadRun") /** * Creates numFiles amount of files.<br> * Counts how many lines are in all the files in one process.<br> * Deletes all the files when finished. * @param numFiles The amount of files to be created. */ public static void countLinesOneProcess(int numFiles) { Initialize(); /* Create Files */ String[] fileNames = createFiles(numFiles); /* Iterate Files*/ long start = System.currentTimeMillis(); LineCounter thread; for (String fileName : fileNames) { thread = new LineCounter(fileName); thread.run(); // same process } long end = System.currentTimeMillis(); System.out.println(String.format("linear time = %d ms, lines = %d", end-start,count)); /* Delete all files */ deleteFiles(fileNames); } public static void main(String[] args) { int num = 1000; countLinesThread(num); countLinesOneProcess(num); } /** * Auxiliary class designed to count the amount of lines in a text file. */// NESTED CLASS LINECOUNTER START: private static class LineCounter extends Thread { /* Privates: */ private String fileName; /* Constructor: */ private LineCounter(String fileName) { this.fileName=fileName; } /* Methods: */ /** * Reads a file and counts the amount of lines it has. */ @Override public void run() { int count=0; try ( // Try with Resources: FileReader fr = new FileReader(fileName); //Scanner sc = new Scanner(fr); BufferedReader br = new BufferedReader(fr); ) { String str; for (str=br.readLine(); str!=null; str=br.readLine()) count++; //for (; sc.hasNext(); sc.nextLine()) count++; incrementCount(count); } catch (IOException e) { System.err.println(String.format("Failed Reading from file: %s", fileName)); } } } // NESTED CLASS LINECOUNTER END; } // CLASS MATALA_4A END;
java java.util.scanner multithreading bufferedreader
Gilad mitrani
source share