2012-08-18 2 views
0
ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L, 
    TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10, true), new 
    ThreadPoolExecutor.CallerRunsPolicy()); 

문제 문을 해제하는 것입니다 : -항상 고유 ID를 얻을 수 및 재사용을 위해

각 스레드 내가 id as zero 몇 번을 얻고 있었다 내 run method에서 1 and 1000 및 프로그램 사이 unique ID60 minutes or more에 대한 실행해야합니다 내가 (if(id==0)) 체크를했고 그 루프 아래에 브레이크 포인트를 두었을 때 나는 왜 그런지 모른다. availableExistingIds가 1에서 1000 사이의 값을 가지므로이 위치가 어디인지 알 수 없습니다. zero is coming in my id? 다음은

class IdPool { 
    private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>(); 

    public IdPool() { 
     for (int i = 1; i <= 1000; i++) { 
      availableExistingIds.add(i); 
     } 
    } 

    public synchronized Integer getExistingId() { 
     return availableExistingIds.removeFirst(); 
    } 

    public synchronized void releaseExistingId(Integer id) { 
     availableExistingIds.add(id); 
    } 
} 


class ThreadNewTask implements Runnable { 
    private IdPool idPool; 
    private int id; 

    public ThreadNewTask(IdPool idPool) { 
     this.idPool = idPool; 
    } 

    public void run() { 
     try { 
     id = idPool.getExistingId(); 
    //Anything wrong here? 
       if(id==0) { 
     System.out.println("Found Zero"); 
     } 
     someMethod(id); 
     } catch (Exception e) { 
     System.out.println(e); 
     } finally { 
     idPool.releaseExistingId(id); 
     } 
    } 

// This method needs to be synchronized or not? 
    private synchronized void someMethod(Integer id) { 
     System.out.println("Task: " +id); 
// and do other calcuations whatever you need to do in your program 
    } 
} 

프로그램이

public class TestingPool { 
    public static void main(String[] args) throws InterruptedException { 
     int size = 10; 
     int durationOfRun = 60; 
     IdPool idPool = new IdPool(); 
     // create thread pool with given size 
     ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size), new ThreadPoolExecutor.CallerRunsPolicy()); 

     // queue some tasks 
     long startTime = System.currentTimeMillis(); 
     long endTime = startTime + (durationOfRun * 60 * 1000L); 

     // Running it for 60 minutes 
     while(System.currentTimeMillis() <= endTime) { 
      service.submit(new ThreadNewTask(idPool)); 
     } 

     // wait for termination   
     service.shutdown(); 
     service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    } 
} 

업데이트 starting- 인에서 메인 클래스입니다 : -

여기에 ArrayBlockingQueue를 사용하는 생각 때문에 대신 충돌의 어떤이없는 경우 있음 사용 가능한 ID가 있으면 사용 가능할 때까지 기다립니다. 아무도 내가 여기 어떻게 사용할 수 있습니까?

코드 BlockingQueue 구현 후 변경.

public void run() { 
    System.err.println(command.getDataCriteria()); 
    if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_PREVIOUS)) { 
    try { 
     System.out.println(command.getDataCriteria()); 
     // Getting existing id from the pool 
     existId = existPool.take(); 
     attributeGetSetMethod(existId); 
    } catch (Exception e) { 
     getLogger().log(LogLevel.ERROR, e.getLocalizedMessage()); 
    } finally { 
     // And releasing that existing ID for re-use 
     existPool.offer(existId);  
    } 
    } 


else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) { 
    try { 
     System.out.println(command.getDataCriteria()); 
     // Getting new id from the pool 
     newId = newPool.take(); 
     attributeGetSetMethod(newId); 
    } catch (Exception e) { 
     getLogger().log(LogLevel.ERROR, e.getLocalizedMessage()); 
    } finally { 
     // And releasing that new ID for re-use 
     newPool.offer(newId); 
    } 
    } 
} 

당신이 run method 내 위의 코드를 보면 그냥 아래 else if loop에서 IS-나타났습니다 하나 개 이상한 것은 내가 권리로 발생하지 않아야 다음 또한이 else if block(which is for New)에 입력 가져옵니다 command.getDataCriteria() is Previous 경우 .equals check을하고 있습니까? 왜 이런 일이 일어나는거야?

else if(command.getDataCriteria().equals(PDSLnPConstants.DATA_CRITERIA_NEW)) { 

답변

1

id = 0 (동기화를 사용하지 않아서 정의되지 않은 동작이 발생할 수 있음) 외에도 ID 풀이 고갈 (비어 있음)되는 시나리오가 있습니다. 이 경우 다음 줄이 표시됩니다.

id = idPool.getExistingId(); 

은 NoSuchElementException으로 실패합니다. 이 경우, finally 블록이 실행됩니다 : 첫 번째 줄에 실패한 이후

idPool.releaseExistingId(id); 

그러나 id 여전히 0의 기본 값을 갖게됩니다. 그래서 당신은 결국 "풀어"0 끝나고 풀로 결코 시작하지 않았더라도 그것을 id 풀에 다시 추가합니다. 그런 다음 나중에 작업을 합법적으로 0 걸릴 수 있습니다.

그러나 catch 블록에서 예외가 발생해야합니다.

+0

제안에 감사하는 표를하십시오. 네, 그렇게 생각합니다. 제 경우에는 제로가 필요하지 않습니다. 그렇다면 현재 코드에서이 상황을 어떻게 극복 할 수 있습니까? 이견있는 사람? – ferhan

+0

하지만 제 경우에는 항상 기존 ID를 공개하므로 요소는 항상 idPool 권한에 있어야합니다. – ferhan

+0

여기 도와 줄 수 있습니까? – ferhan

0

자바 (자바 5 이후)를 제공 Semaphore 내가 너희를 counting semaphore보고있다 생각합니다.

+0

제안에 대한 감사의 판게아. 내 코드에 대한 예제를 제공 할 수 있습니까? 그것은 이러한 것들을 이해하는 데 큰 도움이 될 것입니다. – ferhan

관련 문제