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 回答