2014-10-03 1 views
0

하나는 배열 목록을 읽어 화면에 개체를 페인트 :자바 페인트 '망가'-list 동시성 내 응용 프로그램의

간단한 코드 요약 :

@Override 
public synchronized void paintComponent(Graphics g) { 
    for(Object gO:paintList) { 
    g.drawImage(gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null); 
    } 
} 

이 문제는 내가 때마다 더 많은 개체를 추가한다 사용자가 마우스를 클릭하기 때문에 사용자가 충분히 빨리 클릭하면 쓰기가 진행되는 동안 읽을 수 없으므로 프로그램 페인팅이 더듬 거릴 수 있습니다 (arrayList가 동기화 됨). 개발자가이 동시성 문제를 처리하기 위해 사용하는 일반적인 방법은 무엇입니까?

편집 : 여기에 다시 그리기를 호출하는 코드입니다 :

byte ticks = 0; 
    while(true) { 
     currentTime = System.nanoTime(); 
     if(ticks == 25) { 
      drawPanel.repaint(); 
      ticks = 0; 
     } else if (ticks%5 == 0) {//if ticks is a multiple of 5 (5,10,15,...) 
      drawPanel.operations(); 
      ticks++; 
     } else if(ticks < 25) { 
      ticks++; 
     } 
     try { 
      /* 
      Refer to: 'http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep' 
      on differences between Thread.sleep() and wait() 
      */ 
      wait(1);//old timings: (long)(refreshRate*1000) 
     } catch (InterruptedException ex) { 
      Logger.getLogger(DeathWish.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     //Debugging 
     //System.out.println(ticks); 
     currentTime = System.nanoTime(); 

* 여기서 작업(), '도색'개체의 속성의 변화를 계산 특정 조건을 만족하는 개체를 제거하고 페인트 목록에 새 객체를 추가합니다 . 논리적으로 나에게 추가와 글을 구분해야합니까? 충분한 정보가 없으면 operations() 메소드를 게시 할 수 있지만 해석하기 쉽도록 코드의 거대한 부분을 게시하지 않으려 고합니다.

+0

일반적으로 화면을 연속적으로 칠하는 단일 루프가 있으며 개체를 추가하기 위해 클릭하는 것과 같은 이벤트를 처리하는 다른 루프가 있습니다. 그런 식으로 이벤트 핸들러가 무언가에 달라 붙으면 페인트 루프가 끊김없이 계속 실행됩니다. – Jon

+2

나는 사용자가 잠금 장치를 얻을 수있는 것보다 더 빨리 클릭 할 수 있는지 의심 스럽다. 잠금 획득은 약 25ns입니다. 사용자 클릭 수는 약 50ms입니다. –

+0

예외가 있습니까? – Dimitri

답변

1

난 당신이 동기화 조금 잘못된 물건을 받고있어 추측이 :

  • 의 ArrayList는 동기화 동기화 된 방법은 한 번에 한 스레드가 메소드에 액세스 할 수 있음을 의미합니다
  • 없이 구현 목록입니다 만 함수 내의 변수가 전혀 동기화되지 않았습니다.

원하는 것은 일시적으로 목록을 동기화하는 것입니다.

당신은 그런 식으로 뭔가를 할 수 :

@Override 
public void paintComponent(Graphics g) { 
    synchronized(paintList) { 
    for(Object gO:paintList) { 
     g.drawImage(gO.getObjImage(), gO.getXLoc(), gO.getYLoc(), outer.getTransparent(), null); 
    } 
    } 
} 

및 요 목록 코드를 추가하는 객체에

다소 동일 않습니다. 여기에서

편집 :

당신이 추가 스레드 및 페인트 스레드 사이의 모든 동시성 문제를 제거하려면, 여기 당신이 할 수있는 방법은 다음과 같습니다

이미지를 추가하는 방법 :

public synchronized void addImage(...) { 
    Something newImage = ..... 
    List<Something> newPaintList = new ArrayList<>(paintList.size() + 1); 
    newPaintList.addAll(paintList); 
    newPaintList.add(newImage); 
    paintList = newPaintList; 
} 

그리고 페인트 방법에서 동기화 부분을 제거하십시오.

이렇게하면 paintList에 대한 작업 만 읽기이므로 읽기와 쓰기 사이에 동시성이 없습니다.

동시에 두 개의 다른 스레드가 이미지를 추가하지 않도록 addImage를 동기화해야 하나의 addImage를 무시할 수 있습니다.

+0

문제가 동기화되면 사용자가 목록에 항목을 더 많이 생성하는 동안 페인트 스레드가 대기중인 것 같습니다. –

+0

이 add 메쏘드는 기본적으로 콜렉션이 변경 될 때마다 새로운 복사본이 만들어지는'CopyOnWriteArrayList'와 기본적으로 같은 원리입니다. 그러나 구체적인 코드에 대해 감사드립니다. –