public void processFiles(List<File> files) {
		final ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
		for(File file : files){
			IDocument<String, String> document = config.getDocumentBuilder().createDocument(file.getAbsolutePath());
			final ArrayList<Future<IDocument<String,String>>> futures = new ArrayList<Future<IDocument<String,String>>>();
			try {
				StringAnnotatorEnum.SENTENCE.getAnnotator().annotate(document);
				Collection<? extends IAnnotation<String>> sentences = document.getAnnotations(StringAnnotatorEnum.SENTENCE.getAnnotator().getClass());
				for(IAnnotation<String> sentence : sentences){
					SentenceCallable sentCaller = new SentenceCallable(sentence);
					Future<IDocument<String,String>> future = executor.submit(sentCaller);
					futures.add(future);
				}
				for(Future<IDocument<String,String>> future : futures){
					try {
						IDocument<String,String> sent = future.get();
						for(Class<? extends IAnnotator> annotator : sent.getDocumentAnnotations().keySet()){
							document.addAnnotations(annotator, sent.getAnnotations(annotator));
						}
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (ExecutionException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			} catch (IncompatibleAnnotationException e) {
				e.printStackTrace();
			}
			document.retainAnnotations(config.getOutputIncludedAnnotators()); // Create subset of annotations to be present in the output.
			document.filterAnnotations(config.getFilters()); // Remove the annotations specified by the filters.
			config.getOutputWriter().processDocument(config.getOutputLocation() + "/" + file.getName(), AnnotationUtils.collateAnnotations(document.getDocumentAnnotations(), config.getOutputIncludedAnnotators()));
		}
		executor.shutdown();
	}