java - 如何确保打印偶数奇数的两个线程在此实现中保持先偶后奇的顺序?

标签 java multithreading

我创建了两个可运行的作业:PrintEvenNumbersJob 和 PrintOddNumbersJob,并生成了两个线程来执行这些作业。这似乎工作得很好!但我对这个实现感到有些可疑。我可以对此实现有一些意见和建议吗?

我在这个实现中看到的问题是,只有当 thread1 首先获得对象锁的锁时,程序才会终止,否则它会打印奇数第一偶数第二顺序,并且不会终止,除非我在 PrintEvenNumbersJob 中的 for 语句之后提供另一个语句“lock.notify”(如本实现中所示)。我的问题是如何确保 thread1 首先执行。

public class PrintEvenNumbersJob implements Runnable {

private Object lock;

public PrintEvenNumbersJob(Object lock) {
    this.lock = lock;
}

@Override
public void run() {
    synchronized (lock) {
        for (int i = 0; i <= 10; i += 2) {

            lock.notify();

            System.out.println(i);

            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        lock.notify(); // not required if thread1 gains lock first
    }
}

}


public class PrintOddNumbersJob implements Runnable {

private Object lock;

public PrintOddNumbersJob(Object lock) {
    this.lock = lock;
}

@Override
public void run() {
    synchronized (lock) {
        for (int i = 1; i < 10; i += 2) {

            lock.notify();

            System.out.println(i);

            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        lock.notify();
    }
}

}



public class EvenOddManager {

public static void main(String[] args) {

    Object lock = new Object();

    PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
    PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);

    Thread thread1 = new Thread(printEvenNumbersJob);
    Thread thread2 = new Thread(printOddNumbersJob);

    thread2.start();
    thread1.start();

}

}

最佳答案

您尝试过使用信号量吗?这更容易,因为你不需要担心 wait 和 notification 的调用顺序(如果你在 wait 之前调用 notification,它就会“丢失”)

示例代码:

import java.util.concurrent.*;

public class Test {

    private final Semaphore oddJobPermits = new Semaphore(0);
    private final Semaphore evenJobPermits = new Semaphore(1);

    private class EvenJob implements Runnable {
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    evenJobPermits.acquire();
                    System.out.println(i * 2);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    oddJobPermits.release();
                }
            }
        }
    }

    private class OddJob implements Runnable {
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    oddJobPermits.acquire();
                    System.out.println(i * 2 + 1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    evenJobPermits.release();
                }
            }
        }
    }

    public void run() {
        new Thread(new EvenJob()).start();
        new Thread(new OddJob()).start();
    }

    public static void main(String[] args) {
        new Test().run();
    }

}

关于java - 如何确保打印偶数奇数的两个线程在此实现中保持先偶后奇的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22976412/

相关文章:

java - 水平或垂直循环二维数组的效率

java - 如何防止 Jsoup 在 http 错误时抛出异常?

c# - File.Copy() 在多线程 C# 程序中复制损坏的文件

android - 在一个线程中使用等待和通知

C++ 11 线程,错误调用纯虚函数

Android SurfaceView,已调用 OnDraw 但显示不会在没有 invalidate() 的情况下更新

python - 在 python 日志记录中显示线程 native_id

java - 原子引用

java - 如何从 Java Spring MVC 3.0 Webapp 流式传输文本响应

java - 和引擎库上的颜色设置