0
ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L,
    TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10, true), new 
    ThreadPoolExecutor.CallerRunsPolicy());

問題の説明は次のとおりです。-

各スレッドはunique IDbetween1 and 1000を使用し、プログラムは実行する必要があります。チェックを行っ60 minutes or moreたときに数回run method取得し、そのループの下にブレークポイントを設定しました。理由はわかりません。availableExistingIdsの値は1から1000の範囲であるため、これがどこから来たのかわかりません。id as zero(if(id==0))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); 
    }
}

アップデート:-

ここでArrayBlockingQueueを使用して、使用可能なIDがないときにクラッシュするのではなく、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);   
    }
    }
}

私が今気づいた奇妙なことの1つは、以下のelse if loopように、上記のコードが表示されているrun method場合はcommand.getDataCriteria() is Previous、それが入力されてelse if block(which is for New)いること.equals checkです。なぜこれが起こっているのですか?

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

2 に答える 2

1

id = 0を取得できるシナリオの1つは(同期を使用していないために未定義の動作が発生する可能性があることを除いて)、IDプールが使い果たされた(空の)場合です。それが起こったとき、次の行があります。

id = idPool.getExistingId();

NoSuchElementExceptionで失敗します。この場合、finallyブロックは実行されます。

idPool.releaseExistingId(id);

ただし、最初の行が失敗したため、idデフォルト値は引き続きです。0そのため、最初はプールに含まれていなかったとしても、 「解放」0してIDプールに追加し直すことになります。その後、後のタスクが0合法的に行われる可能性があります。

ただし、これにより、例外が発生した場合は、catchブロックに例外が出力されます。

于 2012-08-18T04:35:35.420 に答える
0

Javaは(Java 5以降)セマフォを提供します。あなたはセマフォのカウントを検討していると思います。

于 2012-08-18T04:14:07.803 に答える