简体   繁体   English

java:使用2个线程打印奇数

[英]java: Printing odd even numbers using 2 threads

I am trying to print odd and even numbers using 2 different threads alternately. 我正在尝试使用2个不同的线程交替打印奇数和偶数。 I was able to achieve it using wait, notify and synchronize block but now i want to evaluate if we can achieve it without using wait, notify and synchronize. 我能够使用等待,通知和同步块来实现它,但是现在我想评估是否可以不使用等待,通知和同步来实现它。

Following is the code i have but its not working: 以下是我拥有的代码,但无法正常工作:

public class OddEvenUsingAtomic {

AtomicInteger nm = new AtomicInteger(0);
AtomicBoolean chk = new AtomicBoolean(true);

public static void main(String args[]) {
    final OddEvenUsingAtomic pc = new OddEvenUsingAtomic();

    new Thread(new Runnable() {

        @Override
        public void run() {
            while (true) {

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                if (pc.chk.compareAndSet(true, false)) {

                    System.out.println("Odd: " + pc.nm.incrementAndGet());
                }
            }

        }

    }).start();

    new Thread(new Runnable() {

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            while (true) {
                if (pc.chk.compareAndSet(false, true)) {

                    System.out.println("Even: " + pc.nm.incrementAndGet());
                }
            }

        }

    }).start();
}

} }

Any ideas? 有任何想法吗?

I created another version after suggestions from Bruno which seems to be working better: 我根据Bruno的建议创建了另一个版本,该版本似乎效果更好:

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class OddEvenUsingAtomic {

    AtomicInteger nm = new AtomicInteger(0);
    AtomicBoolean chk = new AtomicBoolean(true);

    public static void main(String args[]) {
        final OddEvenUsingAtomic pc = new OddEvenUsingAtomic();

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    if (pc.chk.get() == Boolean.TRUE) {

                        System.out.println("Odd: " + pc.nm.incrementAndGet());
                        pc.chk.compareAndSet(true, false);
                    }
                }

            }

        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                while (true) {
                    if (pc.chk.get() == Boolean.FALSE) {

                        System.out.println("Even: " + pc.nm.incrementAndGet());
                        pc.chk.compareAndSet(false, true);
                    }
                }

            }

        }).start();
    }
}

The code is not correctly synchronized, that's the problem. 代码未正确同步,这就是问题所在。

The following execution order is allowed in your code: 您的代码中允许以下执行顺序:

  1. First thread sees chk == true , sets it to false and enters the if block. 第一个线程看到chk == true ,将其设置为false并进入if块。
  2. Second thread sees chk == false , sets it to true and enters the if block. 第二个线程看到chk == false ,将其设置为true并进入if块。

Now, you have 2 threads both inside their if blocks, getting ready to: 现在,您的if块中都有2个线程,准备执行以下操作:

  1. incrementAndGet() the number incrementAndGet()
  2. Print it. 打印它。

Therefore, you have absolutely no control on what is going to happen. 因此,您绝对无法控制将要发生的事情。

  • You can have any of the threads call incrementAndGet() , therefore you can have thread "Odd" printing, first, an odd number, and later, an even number. 您可以让任何线程调用incrementAndGet() ,因此可以让线程“ Odd”打印,第一个是奇数,第二个是偶数。
  • You can have the first thread print the number, loop, see that the condition is satisfied again (since the second thread has set chk to true again, print, all of this before the second thread had the chance to print). 您可以让第一个线程打印出数字,循环,再次满足条件(由于第二个线程将chk再次设置为true ,所以打印,所有这些都在第二个线程有机会打印之前)。

As you can see, to achieve the result you want, you must have the following operations done atomically: 如您所见,要获得所需的结果,必须原子完成以下操作:

  • compareAndSet() the boolean compareAndSet()布尔值
  • incrementAndGet() the number incrementAndGet()
  • print it 打印它

If the 3 operations are not atomic, then you can have the threads being scheduled to run the operations in any possible order, you have no control on the output. 如果这3个操作不是原子操作,则可以安排线程以任何可能的顺序运行这些操作,而您无法控制输出。 The easiest way to achieve this is to use a synchronized block: 实现此目的的最简单方法是使用同步块:

public static void main(final String... args) {
  final Object o = new Object();
  // ... thread 1 ...
    synchronized(o) {
      if (boolean is in the expected state) { change boolean, get number, increment, print }
    }
  // ... thread 2 ...
    synchronized(o) {
      if (boolean is in the expected state) { change boolean, get number, increment, print }
    }
}

Here are two threads printing odds and evens with no wait, notify, or synchronized (at least not in the code you can see): 这是两个线程在没有等待,通知或同步的情况下打印出奇数和偶数(至少在您看不到的代码中):

import java.util.concurrent.*;

public class ThreadSignaling {
    public static void main(String[] args) {
        BlockingQueue<Integer> evens = new LinkedBlockingQueue<>();
        BlockingQueue<Integer> odds = new LinkedBlockingQueue<>();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(() -> takeAndOfferNext(evens, odds));
        executorService.submit(() -> takeAndOfferNext(odds, evens));
        evens.offer(0);
    }

    private static void takeAndOfferNext(BlockingQueue<Integer> takeFrom,
                                         BlockingQueue<Integer> offerTo) {
        while (true) {
            try {
                int i = takeFrom.take();
                System.out.println(i);
                offerTo.offer(i + 1);
            } catch (InterruptedException e) {
                throw new IllegalStateException("Unexpected interrupt", e);
            }
        }
    }
}
class MultiThreading {

    Integer counter = 0;
    Thread even;
    Thread odd;
    boolean flagEven = true;
    boolean flagOdd;

    class ThreadEven implements Runnable {
        @Override
        public void run() {
            try {
                while (counter < 100) {
                    if (flagEven) {
                        System.out.println(counter);
                        counter++;
                        flagEven = false;
                        flagOdd = true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class ThreadOdd implements Runnable {
        @Override
        public void run() {
            try {
                synchronized (even) {
                    while (counter < 100) {
                        if (flagOdd) {
                            System.out.println(counter);
                            counter++;
                            flagOdd = false;
                            flagEven = true;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void start() {
        even = new Thread(new ThreadEven());
        odd = new Thread(new ThreadOdd());
        even.start();
        odd.start();
    }

}

} }

call in the main method 调用main方法

new MultiThreading().start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM