2013-03-07 4 views
0

이것은 Android 프로그래밍에 대한 나의 진정한 진출 이었지만, Java 문제 - ScheduledThreadPoolExecutor의 작동 방식에 대한 주요한 오해 일이 있습니다. AnimatedSprites의 AndEngine 문제라는 생각을 즐겁게하기 위해). 본질적으로, 나는 onFling이 발생할 때까지 스프라이트가 움직이지 않게하기를 원한다. 스프라이트가 움직이며 1 초 후 다시 정지합니다. 사용자는 물을 통해 스프라이트를 "수영"하도록 플링 잉 (Fling-ing)을 유지해야합니다. 내가 가지고있는 문제는 애니메이션입니다. 1 초의 시간대에 두 개 이상의 플링이있는 경우 애니메이션은 중지하기 전에 한두 개의 프레임 만 표시하고 "애니메이션 중지"작업이 쌓여있는 것처럼 느낍니다. 나는이 모든 작업을 마친 후 Flings이 길고 올바른 방향인지 확인하고 확인할 것입니다. ScheduledThreadPoolExecutor를 처음 인스턴스화 할 때 풀 크기 인 1을 제공합니다. 이는 내 이해에 따라 한 번에 둘 이상의 작업을 대기열에 배치 할 수 없음을 의미합니다. 그 위에는 .schedule()을 호출하기 전에 작업을 제거하고 그냥 아무것도 없다는 것을 확인합니다. 나는 이것이 단순한 것이라고 확신한다. 이것을 올바르게 사용하는 방법에 대한 오해가있다. 여기에 코드의 관련 부분을 붙여 넣습니다.ScheduledThreadPoolExecutor를 사용하여 AndEngine에 대한 작업을 반복적으로 예약하십시오.

... 

private ScheduledThreadPoolExecutor shed = new ScheduledThreadPoolExecutor(1); 
private Runnable slowDown = new Runnable(){ 
    public void run(){ 
     if (eelSprite.isAnimationRunning()) 
      eelSprite.stopAnimation(0); 
    }; 
}; 

... 

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
     float velocityY) { 

    shed.remove(slowDown); 
    shed.schedule(slowDown, 1000, TimeUnit.MILLISECONDS); 

    if (!(eelSprite.isAnimationRunning())) 
     eelSprite.animate(frame_duration, 0, 12, true); 

return false; 
} 

답변

0

문제는 까다로운 주제를 다루고 있습니다. 첫 번째 의견으로 ExecutorService을 다룰 때 인터페이스와 코딩이 아닌 코딩에 집중해야한다고 강조하고 싶습니다. 이것은 당신이하려는 것을 복잡하게하지 않아야합니다.

예를 들어, (Scheduled)ExecutorService 인터페이스에는 공개되었지만 존재하지 않는 remove() 메소드의 사용이 언급되어 있습니다. 즉, 이것을 사용하면 완전히 제어 할 수없는 구현 관련 동작이 수반 될 수 있습니다. 제거 방법의 자바 독에서

ThreadPoolExecutor에 :

/** 
* Removes this task from the executor's internal queue if it is 
* present, thus causing it not to be run if it has not already 
* started. 
* 
* <p> This method may be useful as one part of a cancellation 
* scheme. It may fail to remove tasks that have been converted 
* into other forms before being placed on the internal queue. For 
* example, a task entered using {@code submit} might be 
* converted into a form that maintains {@code Future} status. 
* However, in such cases, method {@link #purge} may be used to 
* remove those Futures that have been cancelled. 
* 
* @param task the task to remove 
* @return true if the task was removed 
*/ 

어쩌면 변환 구현에 대한 부분을 참고하시기 바랍니다 Runnable 당신은 불가능 제거() 메소드 때 작동 할 수있어 또 다른 형태로 전달 작업을 제출할 때 사용한 것과 동일한 Runnable 인스턴스를 전달합니다. 또한 제거가 제대로 작동하는지, 이미 시작된 작업인지에 따라 다르다는 보장이 없으므로 경쟁 조건을 확인해야합니다. 그래서이 특별한 방법을 사용하지 말라고 조언합니다.

귀하의 인스턴스가 ScheduledThreadPoolExecutor 인 경우, javadoc도 잘못 읽었을 수 있습니다. 첫째, 가능할 때마다 Executors 클래스가 제공하는 팩토리 메소드를 사용하여 풀을 작성합니다. Executors.newScheduledThreadPool(int) 상태의 자바 독 :

/** 
* Creates a thread pool that can schedule commands to run after a 
* given delay, or to execute periodically. 
* @param corePoolSize the number of threads to keep in the pool, 
* even if they are idle. 
* @return a newly created scheduled thread pool 
* @throws IllegalArgumentException if {@code corePoolSize < 0} 
*/ 

int 인수는 "핵심 풀 크기"의미. 핵심은 여기 키워드입니다. 구현으로 드릴 다운하면 스 니펫에서 호출 한 것과 동일한 메서드가 실제로 사용되므로 여기서는 실제로 변경되지 않습니다. 여기에 약간의 내용을 저장하고 있지만 "핵심"풀 크기는 풀에서 활성 상태로 유지되는 스레드의 최소 수입니다 (일단 풀을 시작하면 풀은 일반적으로 스레드를 선점하지 않으며, 하지만 그것은 구현입니다. 계약서가 아니라면 제가 기억할 수 있습니다.) 이것은 최대 스레드 수와는 아무런 관련이 없습니다. 실제로 드릴 다운하면 실제로 사용한 생성자가 무제한 풀을 만들어 필요한만큼의 스레드를 생성 할 수 있습니다.

결과적으로 풀에 제출하는 작업은 동시에 실행할 수 있습니다.단일 스레드 풀을 원할 경우 Executors.newSingleThreadedScheduledExecutor 팩토리 메서드를 사용할 수 있습니다.

마지막으로 취업이 필요합니다. 그렇다면 일자리를 취소하는 방법은 무엇입니까? 작업을 제출하면 ExecutorService 인스턴스가 보통 Future 개체를 돌려줍니다. 이 Future 객체에는 취소 논리가 포함되어 있습니다. 제출 된 작업에 대해 취소 플래그를 설정할 수 있습니다 (아직 시작되지 않은 경우 실행되지 않도록합니다). 이미 시작된 경우 스레드 중단을 유발할 수도 있습니다.

희망 사항에 따라 의미가 약간 명확 해졌습니다.

+0

와우, 간단한 오해가 너무 많습니다. 나는 "오, 당신은 단지 잊어 버렸습니다 ..."라고 기대하고있었습니다. 그것은 훌륭한 설명이었습니다. 내가해야 할 독서가있는 것처럼 보입니다. 집행자는 내가 생각한 것처럼 분명히 전혀 작동하지 않습니다. – NickGlowsinDark

관련 문제