2015-07-29 2 views
1

Я пытаюсь получить сообщения из facebook с помощью пакетных операций. Я думал о том, чтобы сделать эту задачу многопоточной, чтобы ускорить работу. в основном, им отправляет пакетные запросы в facebook и, ожидая ответа, моя задача выполняет другие действия, которые необходимо выполнить. , когда я отлаживаю задачу (медленно), я получаю результаты 2000, которые хочу получить для теста .... , но когда я запускаю его или позволяю ему отлаживать и приостанавливать после операции запроса, он становится меньше 2000.Почему моя многопоточная задача не работает так, как должна?

String[] str = new String[2000]; 
    ExecutorService exec = Executors.newFixedThreadPool(10); 
    List<BatchRequest> request= new CopyOnWriteArrayList<BatchRequest>(); 
    List <BatchResponse> batchResponses = new ArrayList<BatchResponse>(); 



    int i=1; 
    for(int j=0 ; j<2000; j++) { 

     if (i < 50) { 
      BatchRequest batch = new BatchRequestBuilder(str[i]).build(); 
      request.add(batch); 
      i++; 
      counter++; 
     } else { 
      i = 1; 
      exec.execute(new Runnable() { 

       //thread that gets information from facebook into a list of responses 
       public void run() { 
        // TODO Auto-generated method stub 
        System.out.println("running"); 
        batchResponses.addAll(fc.executeBatch(request)); 
        System.out.println("done"); 

       } 

      }); 
      request.clear(); 
     } 
    } 
    exec.shutdown(); 
    exec.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 

Я удалил все, что не нужно. надеюсь, что это все еще имеет смысл.

Что случилось с моим кодом?

EDIT: ive отредактировал код, чтобы иметь больше смысла. кто угодно?

+0

Возможно, было бы полезно создать пример, иллюстрирующий ту же проблему, что и логика базы данных (т. Е. Вместо rs.next() создать цикл, который повторяется в 2000 раз, и вместо создания массива batchResponses создать массив строк , и т.д.). Это даст нам код, который мы могли бы выполнить и отлаживать напрямую, вместо того, чтобы самим делать эти изменения, чтобы воспроизвести проблему, о которой вы просите. – John

ответ

0

Похоже, что существует некоторая путаница в коде между counter и i. Возможно, если вы объясните, почему вам нужно, чтобы обе эти вещи стали более ясными.

Поскольку код стоит главной проблемой, вы никогда не устанавливаете counter обратно к нулю. Это приведет к тому, что первые 500 будут исполняться как одна партия в своем потоке, но каждый из остальных будет выполнен сам по себе.

+0

счетчик только потому, что база данных im использует 100 000 строк, и я хочу протестировать только 500. нет путаницы об этом. как я уже сказал, если он плохо отлаживает его медленно (с несколькими шагами по шагам), он будет работать нормально. –

1

В дополнение к ответу @OldCurmudgeon я могу сказать, что ArrayList не является потокобезопасным классом. Вы можете использовать другой контейнер, обернуть его Collections.synchronizedList() или добавить синхронизацию с вашим кодом.

Также убедитесь, что ваша ссылка fc ссылается на класс, защищенный потоками.

+0

Я не понимаю, почему это должно быть проблемой, я не использую arrayList где-нибудь рядом с кодом, связанным с потоком .... Я только вставляю в него и в конце кода im перемещаю информацию из нее в базу данных. fc - это DefaultFacebookClient из restfb. Я не думаю, что это потокобезопасность. как сделать его «потокобезопасным»? и, как я сказал OldCurmudgeon ..... ничего плохого в счетчике и я. Этот код работает отлично, когда отлаживается медленно, stepbystep. –

+0

кажется, что я не сделал свою точку зрения. Я считаю, что вставка массива, в которую вставлять, не должна быть проблемой, и я получаю информацию от нее гораздо позже. и снова, доцент, кажется, проблема. ive отредактировал код. надеюсь, что это помогает –

+0

Вы получаете доступ к 'batchResponses' из нескольких разных потоков. Существует такая вещь, как Java Memory Model. Речь идет о гарантиях JVM. Одна из них - видимость *. Речь идет о изменениях, сделанных в одном проходе, видимых от других. По умолчанию JVM не гарантирует видимость. Вам нужно приложить особые усилия для его достижения. Например, используйте синхронизацию. – talex

0

Некоторые проблемы: BatchRonsponses осуществляется через резьбу, а также вы вставляете ее в основной поток. Также batchResponses не является потокобезопасным, поэтому его необходимо синхронизировать.

Также вы делаете request.clear в основной теме ... Это ошибка, поскольку вы не можете гарантировать, что новый поток выполнил, может быть, если новый поток запускается после того, как вы его очистили. И новый поток увидит request.size (0) = 0.

Основной блок if и block имеет тот же код потока, который немного запутан. if (i == 50) вы получаете в блоке и выполняете запросы. , когда ваш счетчик равен 500, вы уже посетили блок else 10 раз, чтобы у вас может быть пустой запрос или последние 50, которые вы вставили.

В этом коде не указано.

+0

им известно, как запутанный мой код, но это не заключительный этап моего кода ... он так запутан, когда я попытался исправить ошибку, о которой я говорю. о двух блоках, имеющих одинаковый код, thats (как я сказал), потому что im работает тест на 500 строк из моего набора результатов, а не весь набор результатов, который намного больше. об очистке запроса во время использования потока - читайте где-нибудь, что это нормально, если im использует правый объект (CopyOnWriteArrayList в этом случае) , если вы считаете, что это проблема, каково решение? какой другой способ вы предлагаете? –

+0

Я редактировал код, чтобы иметь больше смысла. пожалуйста, взгляните еще раз –

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