2015-03-27 4 views
0

Я провел некоторое исследование и не смог найти решение этой проблемы.Где я должен использовать синхронизированный?

Из этой темы Synchronization, When to or not to use? я понимаю, что могу использовать synchronized, но это не решает проблему.

Дело в том, что у меня есть метод, в котором Thread используется для создания ArrayList. В том же Thread еще один method вызывается после того, как BufferedReader закончил чтение файла, и строки добавляются в первый список.

Во втором методе первый список используется для создания второго списка. Когда все это будет сделано, первый метод использует второй список.

Это код, который я использую, если есть что-то непонятное, спросите, и я постараюсь предоставить необходимую информацию.

public synchronized void theBaseList() { 
    Thread t = new Thread() { 
     @override 
     public void run() { 
      try(
       while((line = br.readLine()) != null) { 
        firstList.add(line): 
       } 
      } 
      nextMethod(); 
      currentObject = (Object[]) secondList.get(0); // throws an exception 
      } 
     } 
    }; 
    t.start(); 

public synchronized void nextMethod() { 
    Thread t1 = new Thread(){ 
     double objectListSize = calculateObjectListLength(firstList.size()); 
     @override 
     public void run() { 
      try { 
       // create Objects 
       secondList.add(objects); 
      } 
     } 
     }; 
     t1.start(); 
} 

Когда я использую в nextMethod()Thread создать новый list объектов из элементов в первом списке, я получаю ArrayIndexOutOfBoundsException говоря

Исключение в потоке " Thread-4 "java.lang.IndexOutOfBoundsException: Индекс: 0, Размер: 0

Я избегал этого, не используя Thread во втором методе, и все работает нормально.

Если я использую 2 Threads и делаю оба метода synchronized, он по-прежнему исключает.

Возможно ли это или я должен просто решить, не используя Thread во втором методе? Я думал, synchronized был для решения подобных проблем. Я не понимаю, почему это не работает.

+0

ли вы имеете в виду »методы при работе в отдельных потоках? – EJP

+0

@EJP Да, один метод получает вызов из потока в первом методе. – WonderWorld

+0

Здесь, по-видимому, нет причин использовать отдельные потоки. Операции являются серийными. 't1' зависит от' t', чтобы завершить заполнение первого списка, а 't' зависит от' t1', чтобы добавить ко второму списку. – Radiodef

ответ

2

Предположим, что ваши методы определены в классе с именем Sample, и вы создали экземпляр mySample. Это, по-видимому, то, что делает ваш код:

main thread calls mySample.theBaseList() and synchronizes by locking on mySample. 
    theBaseList() defines thread1 and starts it. 
    theBaseList() exits scope, thus unlocking on mySample. 

thread1 reads in the lines of a file and adds them to list1 (these operations are not synchronized) 
thread1 calls mySample.nextMethod() 
mySample.nextMethod() synchronizes by locking on mySample 
    nextMethod() defines thread2 and starts it. 
    nextMethod() exits scope, thus unlocking on mySample. 

* thread2 sets up list2 (these operations are not synchronized) 
* thread1, having returned from nextMethod() reads from list2 (these operations are not synchronized) 

Последние две операции являются причиной вашего состояния гонки.

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

nextMethod(); 
synchronized(secondList) { 
    currentObject = (Object[]) secondList.get(0); // should no longer throw an exception 
} 

synchronized(secondList) { 
    // create Objects 
    secondList.add(objects); 
} 

EDIT:

synchronized(secondList) { 
    nextMethod(); 
    secondList.wait(); 
    currentObject = (Object[]) secondList.get(0); // should no longer throw an exception 
} 

synchronized(secondList) { 
    // create Objects 
    secondList.add(objects); 
    secondList.notifyAll(); 
} 
+0

Я не знал, что 'synchronized' может использоваться снаружи или в этом случае внутри объявления метода. – WonderWorld

+0

Это не решит проблему. 't' все еще может получить блокировку, пока список пуст. – Radiodef

+0

Ах, ты прав @ Радиод. t может либо дождаться, пока не будет заполнен второй список, либо t2 не будет создан в первую очередь. – chiaboy

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