2

2 つのセマフォへの排他的アクセスを取得した場合にのみアクションを実行するスレッドがあります。

public void run(){
            boolean a1=false;
            boolean a2=false;
            boolean a3=false;
            while(true){
                try{
                    if(res[1].tryAcquire()==true){
                        a1=true;
                        if((res[2].tryAcquire()==true){
                            a2=true;
                            if(res[3].tryAcquire()==true)){
                                a3=true;
                                System.out.println("Rolled the tobacco");
                            }
                        }   
                    }
                }
                finally{
                    if(a1){
                        a1=false;
                        res[1].release();
                    }
                    if(a2){
                        a2=false;
                        res[2].release();
                    }
                    if(a3){
                        a3=false;
                        res[3].release();
                    }
                }
            }
        }
    }

セマフォの取得カウントを混乱させないように、これを記述するより良い方法はありますか? セマフォが現在のスレッドによって取得されているかどうかを確認する方法はありますか?

4

2 に答える 2

2

Java 7 では試用Closeableが可能です。確かにもっと良い解決策があるはずです。

public class Region implements Closeable {

    private final Semaphore semaphore;

    public Region(Semaphore semaphore) {
        this.semaphore = semaphore;
        if (!semaphore.tryAcquire()) {
            throw NotAcquiredException(semaphore);
        }
    }

    @Override
    public void close() {
         semaphore.release();
    }
}

public class NotAcquiredException extends Exception { ... }

使用法:

    public void run() {
        boolean a1 = false;
        boolean a2 = false;
        boolean a3 = false;
        while (true) {
            try (Closeable r1 = new Region(res[1])) {
                 a1 = true;
                 try (Closeable r2 = new Region(res[2])) {
                     a2 = true;
                     try (Closeable r3 = new Region(res[3])) {
                          a3 = true;
                          System.out.println("Rolled the tobacco");
                     } catch (IOException e) {
                     }
                 } catch (IOException e) {
                 }
            } catch (IOException e) {
            }
       }
于 2013-01-09T07:21:17.223 に答える
1

各取得を try に分割できます...最後に、短くはありませんが、いくつかの変数を取り除き、各ロックで何が起こるかをかなり明確にします。(配列をゼロベースに変更しました)

public void run(){
    while(true){
        if(res[0].tryAcquire()){
            try {
                if(res[1].tryAcquire()) {
                    try {
                    if(res[2].tryAcquire()){
                        try {
                            System.out.println("Rolled the tobacco");
                        } finally {
                            res[3].release();
                        }
                    }
                    } finally {
                        res[2].release();
                    }                               
                }
            } finally{
                res[1].release();
            }
        }
    }
}

多くのロックを取得する必要がある場合、または複数の場所でこれを行う必要がある場合は、ヘルパー クラスが便利です。少なくとも、セマフォの取得と解放のボイラープレート コードを非表示にします。

public void run() {
    SemaphoreHelper semaphoreHelper = new SemaphoreHelper(res);
    while (true) {
        try {
            if (semaphoreHelper.aquireAll()) {
                System.out.println("Rolled the tobacco");
            }
        } finally {
            semaphoreHelper.releaseAquired();
        }
    }
}

private static class SemaphoreHelper {

    private final Semaphore[] semaphores;
    private int semaphoreIndex;

    public SemaphoreHelper(Semaphore[] semaphores) {
        this.semaphores = semaphores;
    }

    public void releaseAquired() {
        while (semaphoreIndex > 0) {
            semaphoreIndex--;
            semaphores[semaphoreIndex].release();
        }
    }

    public boolean aquireAll() {
        while (semaphoreIndex < semaphores.length) {
            if (!semaphores[semaphoreIndex].tryAcquire()) {
                return false;
            }
            semaphoreIndex++;
        }
        return true;
    }
}
于 2013-01-09T07:41:15.063 に答える