2013-01-10 2 views
1

응용 프로그램에 java.util.ConcurrentModificationException가 표시되지만 빠른 터치로 여러 번의 터치 이벤트를 수행 할 경우에만 느린 장치 (Samsung Galaxy S)에 더 많은 영향을 미칩니다. 더 빠른 것들 (Galaxy S3)에 반대했다.여러 터치 이벤트 후에 만 ​​java.util.ConcurrentModificationException이 발생 함

나는 int의 배열을 저장하고 해당 행의 점에 대한 불투명도와 데이터를 저장하는 큐가 있습니다. 불투명도가 0에 도달하면 대기열에서 선을 제거하므로 더 이상 그려지지 않습니다. 이들은 대기열을 통해 루프와 내 제거 작업을 수행하는 두 함수입니다

01-10 14:06:27.847: E/AndroidRuntime(2081): java.util.ConcurrentModificationException 
01-10 14:06:27.847: E/AndroidRuntime(2081):  at java.util.LinkedList$LinkIterator.next(LinkedList.java:124) 
01-10 14:06:27.847: E/AndroidRuntime(2081):  at com.android.mcameron.singletrack.Options$TestSurfaceView.drawLinesInvalid(Options.java:559) 
01-10 14:06:27.847: E/AndroidRuntime(2081):  at com.android.mcameron.singletrack.Options$TestSurfaceView.run(Options.java:438) 
01-10 14:06:27.847: E/AndroidRuntime(2081):  at java.lang.Thread.run(Thread.java:1019) 

:

여기 스택 추적입니다.

private void drawLinesInvalid() { 
     paint.setColor(Color.RED); 

     for (Iterator<int[]> iterator = invalidLines.iterator(); iterator.hasNext();) { 
      int[] invalidLine = iterator.next(); // Line 559 with the error 
      float[] line = {invalidLine[1], invalidLine[2], invalidLine[3], invalidLine[4]}; 

      Xfermode originalXfermode = paint.getXfermode(); 
      paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 
      mCanvas.drawLines(line, paint); 
      paint.setXfermode(originalXfermode); 
      paint.setAlpha(invalidLine[0]); 
      mCanvas.drawLines(line, paint); 
     } 
    } 

    private void decreaseLineOpacity() { 
     for (Iterator<int[]> iterator = invalidLines.iterator(); iterator.hasNext();) { 
      int[] line = iterator.next(); 
      if (line[0] <= 0) { 
       iterator.remove(); 
      } 
     } 

     for (Iterator<int[]> iterator = invalidLines.iterator(); iterator.hasNext();) { 
      int[] line = iterator.next(); 
      line[0] -= 10; 
     } 
    } 

여기 공정한 몇 가지 다른 질문을 검토 한 결과, 대부분의 사람들은의 Foreach 루프를 사용하여, 오히려 그 반복자를 큐에 remove() 작업을 수행에 문제가있는 것 같다. 내가 믿는 두 가지 모두 여기에 적용되지 않는다. 또한 위에서 말했듯이 나는 만지면 빠져 나갈 수 있으므로 곧바로 일어나는 오류는 아닙니다. 나는 때때로 예외를 던지기 전에 30-50 개의 imes를 건드릴 수 있습니다. 피터 Lawrey에

+1

코드에 따르면'reducedLineOpacity'와'drawLinesInvalid'가 동시에 호출되고있는 것으로 보입니다. 나는 CopyOnWriteArrayList와 같은 thread safe List를 시도 할 것이다. –

+0

글쎄, 나는 둘 다 내 스레드에서 하나씩 호출하기 때문에 가능하다. –

답변

1

덕분에, 나는이에 CopyOnWriteArrayList

I 변경 내 큐 사용 :

private CopyOnWriteArrayList<int[]> invalidLines = new CopyOnWriteArrayList<int[]>(); 

을 다음이 내 decreaseLineOpacity 업데이트 :

private void decreaseLineOpacity() { 
    int position = 0; 
    for (Iterator<int[]> iterator = invalidLines.iterator(); iterator.hasNext();) { 
     int[] line = iterator.next(); 
     if (line[0] <= 0) { 
      invalidLines.remove(position); 
     } 
     position++; 
    } 

    for (Iterator<int[]> iterator = invalidLines.iterator(); iterator.hasNext();) { 
     int[] line = iterator.next(); 
     line[0] -= 10; 
     Log.d("Counting", "Opacity: "+ line[0]); 
    } 
} 

봤는데 몇 분 동안 클릭하면 예외가 발생하지 않았으므로 좋은 것으로 보입니다.

+0

좋은 일 @ 마크 :) –

0

ListIterator은 안드로이드 서포트 수정에서 LinkedList에 의해 사용됩니다. 따라서 귀하의 문제는 @Peter Lawrey가 제안한 것처럼 멀티 스레딩과 관련되어야합니다. 시도 동기화 두 가지 방법. 이 성능에 영향을 미치는 경우 CopyOnWriteArrayList 시도 할 수 있지만 목록의 복사본을 반복하는 때문에 스레드에서 iterating 동안 가장 많이 업데이트 된 변경 내용을 보장하지 않습니다.