2014-09-30 2 views
0

У меня вопрос.Как я могу запустить группу Thread в Java Code

У меня есть 10000 строк, и я хочу выполнить некоторую операцию над каждым из них. Я хотел бы распараллелить эти операции, чтобы сделать общее время выполнения приемлемым.

Я решил создать нить. В частности, каждые 10 строк я запускаю 10 потоков. Для каждого потока я сохраняю результат в списке.

Я пробовал две версии моего кода. Это моя первая версия.

int size = 10000; 
int cont = 0; 
     int n = 1; 
     String[] arrstr2; 
     int threadgroup = 10; 
if (cont + threadgroup - 1 > size) { 
         arrstr2[i - cont] = subject.toString(); 
        } else { 
         arrstr2[i - cont] = subject.toString(); 
        } 

        if ((i == (threadgroup * n) - 1) || (i == size - 1)) { 

         cont = i + 1; 
         n = n + 1; 
         for (int j = 0; j < arrstr2.length; j++) { 
          Thread t = new Thread(new MyThread(arrstr2[j], l)); 
          t.start(); 

          try { 
           t.join(); 
          } catch (InterruptedException e) { 
           // TODO Auto-generated catch block 
           e.printStackTrace(); 
          } 
         } 
         if (cont + threadgroup - 1 > size) { 
          arrstr2 = new String[size - i - 1]; 
         } 
        } 
        i = i + 1; 

В этой версии я не получаю преимущества в общем исполнении.

Это моя вторая версия:

int size = 10000; 
    int cont = 0; 
      int n = 1; 
      String[] arrstr2; 
      int threadgroup = 10; 
    if (cont + threadgroup - 1 > size) { 
          arrstr2[i - cont] = subject.toString(); 
         } else { 
          arrstr2[i - cont] = subject.toString(); 
         } 

         if ((i == (threadgroup * n) - 1) || (i == size - 1)) { 

          cont = i + 1; 
          n = n + 1; 
          for (int j = 0; j < arrstr2.length; j++) { 
           Thread t = new Thread(new MyThread(arrstr2[j], l)); 
           t.start(); 

          } 
try { 
           Thread.sleep(500); 
          } catch (InterruptedException e) { 
           // TODO Auto-generated catch block 
           e.printStackTrace(); 
          } 
          if (cont + threadgroup - 1 > size) { 
           arrstr2 = new String[size - i - 1]; 
          } 
         } 
         i = i + 1; 

В этом случае я теряю какую-то информацию. MyThread это класс, который делает некоторую обработку и помещает результат в списке Явы:

public class MyThread implements Runnable{ 

    String subject; 
    private List<String[]> l; 

    public MyThread(String subject, List<String[]> l) { 
     this.subject = subject; 
     this.l = l; 
    } 

    @Override 
    public void run() { 

     synchronized (l){ 
     //do something 
     String[] result = new String[2]; 
     result[0] = res0; 
     result[1] = res1; 
     l.add(result); 
    } 
} 

Для моей цели, этот код является правильным? Как я могу запустить группу потоков в Java Code и получить приемлемое время?

+3

Используйте ExecutorService с фиксированным бассейном Thread! :) –

+0

Можете ли вы сделать для меня пример? – Musich87

+0

Посмотрите здесь: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html – PeterMmm

ответ

1

Вот небольшой пример с ExecutorService. Размер резьбы фиксирован до 10, но вы можете настроить его на свои нужды.

StringTask в основном меняет данную строку.

public class Test { 

    private static final int THREADS = 10; 
    private static final int DATA_SIZE = 1000; 

    public static void main(String[] args) { 
     // Declare a new ExecutorService with a maximum of 2 threads. 
     ExecutorService service = Executors.newFixedThreadPool(THREADS); 

     // Prepare a list of Future results. 
     List<Future<String>> futures = new ArrayList<Future<String>>(DATA_SIZE); 

     // Submit the tasks and store the results. 
     for (int i = 0; i < DATA_SIZE; i++) { 
      futures.add(service.submit(new StringTask("Sample String " + i))); 
     } 

     // Accept no new tasks. 
     service.shutdown(); 

     // Retrieve the actual String results. 
     List<String> results = new ArrayList<String>(DATA_SIZE); 
     try { 
      for (Future<String> future : futures) { 
       // The get() method blocks if the execution of the task is not finished. 
       results.add(future.get()); 
       System.out.println(future.get()); 
      } 
     } catch (ExecutionException ee) { 
      System.out.println("Error while getting result!"); 
      ee.printStackTrace(); 
     } catch (InterruptedException ie) { 
      System.out.println("Error while getting result!"); 
      ie.printStackTrace(); 
     } 
    } 

    /** 
    * Callable task that reverses a given String. 
    */ 
    private static final class StringTask implements Callable<String> { 
     private String input; 

     private StringTask(String input) { 
      super(); 

      if (input == null) { 
       throw new NullPointerException(); 
      } 

      this.input = input; 
     } 

     @Override 
     public String call() throws Exception { 
      StringBuilder builder = new StringBuilder(); 

      for (int i = this.input.length() - 1; i >= 0; i--) { 
       builder.append(this.input.charAt(i)); 
      } 

      return builder.toString(); 
     } 
    } 
} 

Я использую Callable здесь вместо того, чтобы Runnable потому что Callable позволяет задачу на самом деле возвращает результат, который мы можем использовать (через интерфейс Future). Если вам нужна только выполненная задача, вы можете просто использовать Runnable!

+0

Это решение хорошее, но в моем случае я получаю сообщение об ошибке.Операция, которую должен выполнять мой поток, в первую очередь связана с выполнением запроса SPARQL (который для краткости я пропустил раньше). В частности, у меня есть QueryExecution exec1 = querymy (stringa, stringa1); Результаты ResultSet1 = ResultSetFactory.copyResults (exec1.execSelect()); Я видел, что потоки правильно запущены, но когда я возвращаю результаты, – Musich87

+0

Я получаю эту ошибку: Ошибка при получении результата! java.util.concurrent.ExecutionException: HttpException: 503 \t на java.util.concurrent.FutureTask.report (FutureTask.java:122) \t в java.util.concurrent.FutureTask.get (FutureTask.java:188) , В частности, я получаю эту ошибку в этом для цикла: for (Future future: futures) { // Метод get() блокирует, если выполнение задачи еще не закончено. results.add (future.get()); System.out.println (future.get()); } – Musich87

+0

@ Musich87 В [ExecutionException] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutionException.html) doc говорит, что это исключение возникает при попытке получить результат задачи, которая прерывается путем исключения исключения. Выполняет ли выполнение запроса SPARQL исключение? Возможно, 'Throwable.getCause()' может помочь вам в этом. –

1

Возможно, вы можете взглянуть на новый Java 8 Stream API. http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html Там вы можете легко распараллелить такие операции.

+0

Действительно, потоки, безусловно, намного сложнее (и менее подвержены ошибкам), чем все, что могут сделать неопытные люди. – specializt

0

Использование Java 8:

List<String> res = Arrays.toStream(arrstr2) 
         .parallel() 
         .map(s -> doWork(s)) 
         .collect(Collectors.toList()); 
+0

s моя строка, не так ли? Кто коллекционеры? – Musich87

+0

Где я могу скачать Java 8 EE для 64-битного? – Musich87

+0

Здесь: https://www.google.com/search?q=jdk8 Но, возможно, вам стоит придерживаться java 7 и использовать ExecutorService, как предложил Алексис Леклерк. –