2014-09-17 3 views
0

У меня довольно большое количество файлов, которые нужно преобразовать в другой формат. Преобразование выполняется через Java-JAR-файл, который получает имя файла в качестве параметра. Теперь у меня есть пакетный файл для Windows, который использует цикл для перебора всех файлов (есть файл, который содержит список всех файлов, которые должны быть преобразованы)Параллельная обработка командного файла Windows

for /F %%i in (all_files.txt) do call java -cp %Classpath% de.xyz.Convert -xml %%i .\xml 

Теперь машина, я хочу, чтобы это сделать на имеет восемь ядер. Количество файлов составляет около 360 000, и я хотел бы, чтобы это заняло как можно меньше времени, поэтому я хотел бы использовать как можно больше ядер. Как я могу использовать несколько ядер как можно проще? Будет ли Windows делать это самостоятельно?

+0

Несомненно, это позволяет управлять одним JVM, уменьшая накладные расходы. Измените свою банку, чтобы взять каталог ввода и обработать все файлы из этого каталога в выходной каталог, а затем разрешить многопоточность. :) - Я думаю, что ваша проблема здесь, скорее всего, будет скоростью чтения диска. –

+0

К сожалению, я не могу изменить файл jar, это «проприетарный». :/ –

+0

Ну, может быть, с большим количеством обратной инженерии я мог бы, но у меня нет на это времени. –

ответ

0

Хорошо, потому что раньше я этого не делал, я сбил это с ног. Это не здорово, и используемая мной библиотека была банкой, которую я создал, чтобы потерпеть крах через 2 минуты. Надеюсь, вы сможете переделать это для своих нужд.

package test; 

import java.io.IOException; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.ThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 


public class Test { 
    public static void main(String[] args) throws InterruptedException, IOException { 
     BlockingQueue<Runnable> runnableQueue = new LinkedBlockingQueue<>(); 
     ExecutorService executorServ = new ThreadPoolExecutor(8, 8, 1, TimeUnit.MINUTES, runnableQueue); 
     runnableQueue.add(new RunCrash("Example")); // Add one for each file... 
     executorServ.shutdown(); 
     while(!executorServ.isTerminated()) { 
      // running 
     } 
    } 
} 

class RunCrash implements Runnable { 

    private String fileName; 
    RunCrash(String fileName) { 
     this.fileName = fileName; 
    } 

    @Override 
    public void run() { 
     System.out.println(fileName); 
     try { 
      crash.CrashMe.main(new String[]{fileName}); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

О, вы можете позволить основной нити умереть до того, как другие закончить, я считаю, что JVM будет держать исполнитель и связанные с ним очередь. :)

+0

Спасибо. Это отличная отправная точка. Спустив основной поток, вы имеете в виду, что я мог бы удалить цикл while? В настоящее время я изо всех сил пытаюсь запустить runnableQueue после добавления только одного потока. Угадайте, мне нужно будет кое-что прочитать :) –

+0

Да, вы можете удалить цикл while. erm ... попробуйте использовать LinkedBlockingQueue вместо SynchronousQueue ..., который должен позволить вам ставить в очередь более одного Runnable за один раз ... (извините, я как бы бросился туда и не проверял все api для релевантности.) –

+0

Без проблем! Я нашел другой пример, где они используют ExecutorService executorService = Executors.newFixedThreadPool (nThreads) ;, который я теперь использую. Затем я выполняю executorService.execute (новый конвертер (имя_файла)) и может работать. К сожалению, JAR-файл теперь, кажется, нуждается в некоторых классах apache, которые, я думаю, мне придется добавлять в качестве внешних библиотек самостоятельно или что-то в этом роде ... Я отчитаюсь, когда у меня это получится :) –