1

セマフォを使用していくつかのスレッドを同期しようとしています。目標は、1 (8 回)、2 (4 回)、4 (2 回)、8 (1 回) のシーケンスをこの順序で繰り返し印刷することです。私のプログラムは、約 90% 完了するまでは正しく動作しますが、2 と 4 でうまくいきません。何が問題を引き起こしているのか、一生わかりません。助言がありますか?

public class ThreadSync
{

private static int count = 100;

private static Semaphore printSomeOnes = new Semaphore(1);
private static Semaphore printSomeTwos = new Semaphore(0);
private static Semaphore printSomeFours = new Semaphore(0);
private static Semaphore printSomeEights = new Semaphore(0);


private static boolean runFlag = true;

public static void main( String[] args ) {

    // create and start each runnable
    Runnable task1 = new TaskPrint1();
    Runnable task2 = new TaskPrint2();
    Runnable task3 = new TaskPrint4();
    Runnable task4 = new TaskPrint8();

    Thread thread1 = new Thread( task1 );
    Thread thread2 = new Thread( task2 );
    Thread thread3 = new Thread( task3 );
    Thread thread4 = new Thread( task4 );

    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();



    // Let them run for 500ms
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }


    // put up the stop sign
    runFlag=false;

    thread4.interrupt();
    thread3.interrupt();
    thread2.interrupt();
    thread1.interrupt();

}

public static class TaskPrint1 implements Runnable 
{
    public void run(){
        while (runFlag) {
            for(int i = 0; i < count; i++){
                if(i % 8 == 0){
                try {                       
                    printSomeOnes.acquire();                        
                }
                catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            System.out.printf( "%s\n", "1");
            if(i % 8 == 0){
            printSomeTwos.release();
            }
            }
        }
    }
}

public static class TaskPrint2 implements Runnable 
{
    public void run(){
        while (runFlag) {
            for(int i = 0; i < count; i++){
                if(i % 4 == 0){
                try {
                    printSomeTwos.acquire();
                }
                catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            System.out.printf( "%s\n", "2");
            if(i % 4 == 0){
            printSomeFours.release();
            }
            }
        }
    }
}

public static class TaskPrint4 implements Runnable 
{
    public void run(){
        while (runFlag) {
            for(int i = 0; i < count; i++){
                if(i % 2 == 0){
                try {
                    printSomeFours.acquire();
                }
                catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            System.out.printf( "%s\n", "4");
            if(i % 2 == 0){
            printSomeEights.release();
                }
            }
        }
    }
}

public static class TaskPrint8 implements Runnable 
{
    public void run(){
        while (runFlag) {
            for(int i = 0; i < count; i++){
                try {
                    printSomeEights.acquire();
                }
                catch (InterruptedException ex) {
                    ex.printStackTrace();
            }
            System.out.printf( "%s\n", "8");
            printSomeOnes.release();
            }
        }
    }
}

}

4

1 に答える 1

0

私が行ったいくつかの変更:

この状況に対処する最善の方法は、 runFlaguseを削除する ことです。Thread.currentThread().isInterrupted()そして、いつInterruptedExceptionでもスレッドの割り込みフラグをリセットして、上位のコードがそれに基づいて動作するようにします。として:

                     try {
                            printSomeOnes.acquire();
                        } catch (InterruptedException ex) {
                            Thread.currentThread().interrupt();
                            break;
                        }

ここでは、いつInterruptedExceptionでもフラグをリセットして、
while (!Thread.currentThread().isInterrupted()) {それに応じて動作できるようにします。これは、これに対処する方法です。それが役に立てば幸い。

public class ThreadSync {

    private static int count = 100;
    private static Semaphore printSomeOnes = new Semaphore(1);
    private static Semaphore printSomeTwos = new Semaphore(0);
    private static Semaphore printSomeFours = new Semaphore(0);
    private static Semaphore printSomeEights = new Semaphore(0);
    private static volatile boolean runFlag = true;

    public static void main(String[] args) {

        // create and start each runnable
        Runnable task1 = new TaskPrint1();
        Runnable task2 = new TaskPrint2();
        Runnable task3 = new TaskPrint4();
        Runnable task4 = new TaskPrint8();

        Thread thread1 = new Thread(task1);
        Thread thread2 = new Thread(task2);
        Thread thread3 = new Thread(task3);
        Thread thread4 = new Thread(task4);

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();



        // Let them run for 500ms
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        // put up the stop sign
//    runFlag=false;

        thread4.interrupt();
        thread3.interrupt();
        thread2.interrupt();
        thread1.interrupt();

    }

    public static class TaskPrint1 implements Runnable {

        @Override
        public void run() {

            while (!Thread.currentThread().isInterrupted()) {

                for (int i = 0; i < count; i++) {
                    if (i % 8 == 0) {
                        try {
                            printSomeOnes.acquire();
                        } catch (InterruptedException ex) {
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                    System.out.printf("%s\n", "1");
                    if (i % 8 == 0) {
                        printSomeTwos.release();
                    }
                }
            }

        }
    }

public static class TaskPrint2 implements Runnable {

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            for (int i = 0; i < count; i++) {
                if (i % 4 == 0) {
                    try {
                        printSomeTwos.acquire();
                    } catch (InterruptedException ex) {
                        Thread.currentThread().interrupt();
                            break;
                    }
                }
                System.out.printf("%s\n", "2");
                if (i % 4 == 0) {
                    printSomeFours.release();
                }
            }
        }
    }
}

public static class TaskPrint4 implements Runnable {

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            for (int i = 0; i < count; i++) {
                if (i % 2 == 0) {
                    try {
                        printSomeFours.acquire();
                    } catch (InterruptedException ex) {
                       Thread.currentThread().interrupt();
                            break;
                    }
                }
                System.out.printf("%s\n", "4");
                if (i % 2 == 0) {
                    printSomeEights.release();
                }
            }
        }
    }
}

public static class TaskPrint8 implements Runnable {

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            for (int i = 0; i < count; i++) {
                try {
                    printSomeEights.acquire();
                } catch (InterruptedException ex) {
                   Thread.currentThread().interrupt();
                    break;
                }
                System.out.printf("%s\n", "8");
                printSomeOnes.release();
            }
        }
    }
}
}
于 2013-10-30T03:54:58.973 に答える