2012-08-06 4 views
0

У меня есть класс. Например:Несколько тем в Java

public class Data { 
    private String name; 

    public Data(String url) { 
     // There is download something from the Internet and set field "name". 
    } 

    public String getName() { 
     return name; 
    } 
} 

В некотором методе мне нужно инициализировать массив объектов Data.

ArrayList<Data> list = new ArrayList<Data>; 
for(int i=0; i<max; i++) { 
    list.add(new Data("http://localhost/" + String.valueOf(i))); 
} 

Но оно длинное. Я хочу сделать это:

final ArrayList<Data> list = new ArrayList<Data>; 
for(int i=0; i<max; i++) { 
    final int tmp = i; 
    new Thread() { 

     public void run() { 
      list.add(new Data("http://localhost/" + String.valueOf(tmp))); 
     } 

    }.start(); 

} 

Но основная тема заканчивается раньше остальных, а список переменных пуст. Что мне делать? Помощь pls:

UP. Это не слишком быстро, чтобы загрузить некоторые данные из Интернета, поэтому я создал несколько потоков.

+1

частный ** type ** name? public ** type ** Data() – 11684

+0

'' http: // localhost/"+ String.valueOf (tmp)' совпадает с '" http: // localhost/"+ tmp' – Autar

+4

Что вы хотите достичь? Ускорить процесс? Запуск новых потоков в каждом цикле сделает вашу программу медленнее. Если вы хотите распараллелить раскол процесса до интеллектуальных джонков, скажем, по 10 элементов каждый. Вы должны найти баланс между накладными расходами и работой рабочего. – alexsb

ответ

3

Вместо того, чтобы дело с деталями низкого уровня API Thread, вы можете использовать параллельный пакет Java, с исполнителем для обработки нити (я не знаю, какие ListArray есть, но если он не является потокобезопасным, у вас возникнут проблемы с предлагаемым решением, некоторые из других ответов: добавление соединения будет недостаточным).

Например, упрощенный пример будет:

final ExecutorService executor = Executors.newFixedThreadPool(10); 
final List<Future<Data>> list = new ArrayList<Future<Data>>(max); 

for (int i = 0; i < max; i++) { 
    final int tmp = i; 
    Callable<Data> c = new Callable<Data>() { 
     @Override 
     public Data call() { 
      return new Data("http://localhost/" + tmp); 
     } 
    }; 
    list.add(executor.submit(c)); 
} 

executor.shutdown(); 

for (Future<Data> future : list) { 
    Data data = future.get(); //will block until the page has been downloaded 
    //use the data 
} 

В идеале, вы whould добавить обработку ошибок вокруг future.get(), так как он будет бросать ExecutionException, если ваша задача генерирует исключение, которое я полагаю может произойти, если например, страница недоступна.

+0

спасибо.Ваш пример очень полезен и умен. – ruslanys

2

1. Когда вы запускаете Другой поток, который выполняет работу по получению данных из сети и заполнению списка, сразу после этого использует метод join().

2.join() метод не будет препятствовать следующей строке выполнить до того, как метод нити, на которой он называетсяrun()имеет отделку().

3. Таким образом, ваш метод main() не будет выполняться до того, как список заполняется, как вы использовали join() держать исполнение до другого потока делаются .....

+4

Предполагается, что ListArray является потокобезопасным. – assylias

+0

Спасибо за теорию. – ruslanys

+0

Добро пожаловать ..... –

1

В главном использовании Thread.join ждать дочерних потоков для завершения

Thread[] threads = new Thread[max]; 
    final List<Data> list = Collections.synchronizedList(new ArrayList<Data>()); 
    for(int i=0; i< max; i++) { 
     final int tmp = i; 
     Thread t = new Thread() { 

      public void run() { 
       list.add(new Data("http://localhost/" + String.valueOf(tmp))); 
      } 

     }; 
     t.start(); 
     threads[i] = t; 
    } 
    for (Thread t : threads) { 
     t.join(); 
    } 
+0

Спасибо за ваш пример! Очень полезно. – ruslanys

Смежные вопросы