猿问

FairSync能否保证执行顺序?

我的第一个问题,谢谢您的帮助!我正在尝试使用两个线程交替打印奇数和偶数 1~100。预期成绩:


    pool-1-thread-1=> 1

    pool-1-thread-2=> 2

    pool-1-thread-1=> 3

    pool-1-thread-2=> 4

    ......

    pool-1-thread-1=> 99

    pool-1-thread-2=> 100

我想我可以使用FairSync,但它只能保证大部分打印是正确的。像这样:


pool-1-thread-1=> 55

pool-1-thread-2=> 56

pool-1-thread-1=> 57

pool-1-thread-2=> 58   

pool-1-thread-2=> 59  //※error print※

pool-1-thread-1=> 60

pool-1-thread-2=> 61

pool-1-thread-1=> 62

不知道为什么极少数情况下订单会丢失?你可以批评我的代码和我的英语。这是我的代码:


private static final int COUNT = 100;


private static final int THREAD_COUNT = 2;


private static int curr = 1;


static ReentrantLock lock = new ReentrantLock(true);


static ExecutorService executorService = Executors.newCachedThreadPool();


public static void main(String[] args) {

    Runnable task = () -> {

        for (; ; ) {

            try {

                lock.lock();

                if (curr <= COUNT) {

                    System.out.println(Thread.currentThread().getName() + "=> " + curr++);

                } else {

                    System.exit(0);

                }

            } catch (Exception e) {

                e.printStackTrace();

            } finally {

                lock.unlock();

            }

        }

    };

    for (int i = 0; i < THREAD_COUNT; i++) {

        executorService.execute(task);

    }

}


翻阅古今
浏览 104回答 2
2回答

蝴蝶刀刀

不,亲爱的,你的实施不正确。哪个线程有机会运行是由操作系统决定的。无法保证线程 1 和 2 会相继执行。您可以通过检查变量 curr 的先前值来修复代码,如果该值不是该线程期望的值,则不要增加并打印。为我:if(curr.threadName.equals("Thread 2") && (curr%2 !=0)){// Print// Increment}

千万里不及你

您不能使用单锁来实现此目的。即使ReentrantLock提供公平性,但它无法控制线程调度。我们可以实现像抛出一样的线程间通信Semaphore。信号量控制线程的执行。我们创建两个线程,一个奇数线程和一个偶数线程。奇数线程将打印从 1 开始的奇数,偶数线程将打印从 2 开始的偶数。创建两个信号量 semOdd 和 semEven,它们一开始有 1 和 0 许可。这将确保首先打印奇数。class SharedPrinter {    private Semaphore semEven = new Semaphore(0);    private Semaphore semOdd = new Semaphore(1);    void printEvenNum(int num) {        try {            semEven.acquire();        } catch (InterruptedException e) {            Thread.currentThread().interrupt();        }        System.out.println(Thread.currentThread().getName() + num);        semOdd.release();    }    void printOddNum(int num) {        try {            semOdd.acquire();        } catch (InterruptedException e) {            Thread.currentThread().interrupt();        }        System.out.println(Thread.currentThread().getName() + num);        semEven.release();    }}class Even implements Runnable {    private SharedPrinter sp;    private int max;    // standard constructor    @Override    public void run() {        for (int i = 2; i <= max; i = i + 2) {            sp.printEvenNum(i);        }    }}class Odd implements Runnable {    private SharedPrinter sp;    private int max;    // standard constructors     @Override    public void run() {        for (int i = 1; i <= max; i = i + 2) {            sp.printOddNum(i);        }    }}public static void main(String[] args) {    SharedPrinter sp = new SharedPrinter();    Thread odd = new Thread(new Odd(sp, 10),"Odd");    Thread even = new Thread(new Even(sp, 10),"Even");    odd.start();    even.start();}
随时随地看视频慕课网APP

相关分类

Java
我要回答