使用信号量同步线程化

时间:2013-10-30 03:05:44

标签: java multithreading semaphore

我正在尝试使用信号量同步一些线程。目标是按顺序重复打印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();
            }
        }
    }
}

}

1 个答案:

答案 0 :(得分:0)

我所做的一些改变:

删除runFlag使用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();
            }
        }
    }
}
}