2016-03-16 2 views
1

Итак, в настоящее время я создаю программу анализа данных и прогнозирования, и для целей тестирования я имитирую большое количество данных (в диапазоне от 10 000 до 1 000 000) «испытаний». Данные представляют собой смоделированный Матч для теоретической игры. Каждый матч имеет раунды. Основная psudocode для программы заключается в следующем:Многопоточность Java для имитации данных

main(){ 
    data = create(100000); 
    saveToFile(data); 
} 

Data create(){ 
    Data returnData = new Data(playTestMatch()); 
} 

Match playTestMatch(){ 


    List<Round> rounds = new List<Round>(); 

    while(!GameFinished){ 
     rounds.add(playTestRound()); 
    } 

    Match returnMatch = new Match(rounds); 
} 


Round playTestRound(){ 
    //Do round stuff 
} 

Прямо сейчас, я задаюсь вопросом, могу ли я справиться моделирование этих раундов в течение нескольких потоков, чтобы ускорить этот процесс. Я НЕ знаком с теорией многопоточности, так что кто-то может помочь мне в этом, или объясните мне, почему это не будет работать (не ускорит процесс). Благодаря!

+0

Ваш код [потокобезопасной] (http://www.javaworld.com/article/2076747/core-java/design-for-thread-safety.html)? –

+0

см. Java.util.concurrent Исполнители и ExecutorService – ControlAltDel

+0

Используйте [Закон Амдаля] (https://en.wikipedia.org/wiki/Amdahl%27s_law), чтобы определить, насколько распараллеливает ваш код, чтобы ускорить его. –

ответ

0

Если ваш код является потокобезопасным, и вы можете разделить задачу на отдельные куски, которые не полагаются друг на друга, тогда это относительно легко. Сделать класс, который делает работу Callable и добавить куски работы в список, а затем использовать ExecutorService, как это:

ArrayList<Simulation> SL=new ArrayList<Simulation>(); 
for(int i=0; i<chunks; i++) 
    SL.add(new Simulation(i); 
ExecutorService executor=Executors.newFixedThreadPool(nthreads);//how many threads 
List<Future<Result>> results=null; 
try { 
    results = executor.invokeAll(SL); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
executor.shutdown(); 
for(Future<Result> result:results) 
    result.print(); 

Таким образом, моделирование является вызываемым и возвращает результат, результаты есть список, который заполняется когда executor.invokeAll вызывается с помощью ArrayList моделирования. Получив результаты, вы можете распечатать их или что угодно. Вероятно, лучше всего установить nthreads, равное количеству доступных вам ядер.

0

Если вы новичок в многопоточности Java, это объяснение может показаться немного трудным для понимания вначале, но я постараюсь сделать его максимально простым.

В целом, я думаю, что в целом, когда у вас есть большие наборы данных, выполняемые операции одновременно с использованием нескольких потоков значительно ускоряют процесс, поскольку они противостоят использованию однопоточного подхода, но, конечно, есть исключения.

Вы должны думать о трех вещах:

  1. Создание темы

  2. Управление Тем результаты

  3. Смежный/обмена, вычисленных для каждого потока с основным потоком

Создание тем: Темы могут создаваться вручную, расширяя класс Thread или вы можете использовать класс Executors. Я бы предпочел, чтобы класс Executors создавал потоки, так как он позволяет создавать пул потоков и управлять потоками для вас. Это позволит вам повторно использовать существующие потоки, которые не работают в пуле потоков, тем самым уменьшая объем памяти приложения. Вы также должны посмотреть на интерфейс ExecutorService, поскольку будете использовать его для возбуждения своих задач.

Управление потоками: Служба исполнителей/исполнителей отлично справляется с управлением потоками автоматически, поэтому, если вы ее используете, вам не нужно беспокоиться о управлении потоками.

Связь: Это ключевая часть всего процесса. Здесь вы должны подробно рассказать о безопасности потоков вашего приложения.

Я бы рекомендовал использовать две очереди для выполнения задания, очередь чтения для чтения данных и запись очереди для записи данных.

Но если вы используете простой ArrayList убедитесь, что вы синхронизировать код безопасности потока, заключая ArrayList в синхронизированный блок

synchronized(arrayList){ 
// do stuff 

}

+0

Так что в основном я пошел вперед и * попробовал * сделать это на слух. Насколько я вижу, он не падает и не горит, и он увеличивает скорость DRAMATICALLY. Вот моя ссылка GitHub Repo, если вам интересно. https://github.com/Schwaitz/CSGORoundAnalysis – Schwaitz

+0

Не зная, почему он не сбой и не горит, несмотря на то, что не используется синхронизированный() блок? – Schwaitz

+0

@kuuy То, как вы обращаетесь к своему «матчи» arraylist, не является идеальным, и в умеренно загруженной системе реального времени может произойти сбой. – rahsan