Skip to content
Mike Angstadt edited this page Apr 4, 2016 · 1 revision

Experimental multi-threading code

Handles the creation of the XML Document objects in a separate thread, while the XML serialization is done in the main thread. Results in about a 10% speed boost. Note that only one thread can interact with the list of ClassDoc objects at a time--warnings are generated when more than one thread tries to process the list. My assumption is that only one thread can write to the ZIP file at a time.

The downside to this approach is that, as the ClassDoc objects are being interacted with, warning messages get printed to stdout. These warning messages do not "sync up" with the status messages that are printed before an XML document is serialized to the ZIP file. In addition, the characters from the status and warning messages sometimes get tangled up. I couldn't find a way to disable or redirect these warning messages without using the -quiet javadoc command argument. I tried calling System.setOut and System.setErr in my doclet class to redirect the output, but the warnings still get printed to the console. I do not want to use -quiet because I still want these warnings printed--I just want control over when they are printed.

A potential workaround would be to separate out the javadoc command output from the progress messages that my own doclet generates. In other words, can my doclet's progress messages be sent to something other than stdout? Using a socket would be one approach. But that's fairly complicated. Plus, adding a socket may decrease performance--worse case, it may negate the performance improvement of the multi-threaded approach.

	/**
	 * Creates the XML files containing the Javadoc information of each class.
	 * @param fs the ZIP file
	 * @param rootDoc the Javadoc information
	 * @throws IOException if there's a problem writing to the ZIP file
	 */
	private static void createClassFilesThreaded(FileSystem fs, RootDoc rootDoc) throws IOException {
		ClassDoc[] classDocs = rootDoc.classes();
		BlockingQueue<ParseResult> queue = new LinkedBlockingQueue<>();
		ProgressPrinter progress = new ProgressPrinter(classDocs.length);

		Thread parseThread = new Thread() {
			@Override
			public void run() {
				for (ClassDoc classDoc : classDocs) {
					Document document = RootDocXmlProcessor.toDocument(classDoc);
					queue.add(new ParseResult(document, classDoc));
				}
			}
		};
		parseThread.setDaemon(true);
		parseThread.start();

		for (int i = 0; i < classDocs.length; i++) {
			ParseResult result;
			try {
				result = queue.take();
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}

			progress.print(result.classDoc);
			Path path = fs.getPath(classFilePath(result.classDoc));
			Files.createDirectories(path.getParent());
			writeXmlDocument(result.document, path);
		}

		System.out.println();
	}

	private static class ParseResult {
		private final Document document;
		private final ClassDoc classDoc;

		public ParseResult(Document document, ClassDoc classDoc) {
			this.document = document;
			this.classDoc = classDoc;
		}
	}
Clone this wiki locally