java:使用2个线程打印奇数 [英] java: Printing odd even numbers using 2 threads

查看:41
本文介绍了java:使用2个线程打印奇数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用2个不同的线程交替打印奇数和偶数.我能够使用等待,通知和同步块来实现它,但是现在我想评估是否可以不使用等待,通知和同步来实现它.

I am trying to print odd and even numbers using 2 different threads alternately. 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();
}

}

有什么想法吗?

我根据Bruno的建议创建了另一个版本,该版本似乎运行得更好:

I created another version after suggestions from Bruno which seems to be working better:

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. 第一个线程看到 chk == true ,将其设置为 false ,然后进入 if 块.
  2. 第二个线程看到 chk == false ,将其设置为 true ,然后进入 if 块.
  1. First thread sees chk == true, sets it to false and enters the if block.
  2. Second thread sees chk == false, sets it to true and enters the if block.

现在,在它们的 if 块中都有两个线程,准备进行以下操作:

Now, you have 2 threads both inside their if blocks, getting ready to:

  1. incrementAndGet()数字
  2. 打印.

因此,您绝对无法控制将要发生的事情.

Therefore, you have absolutely no control on what is going to happen.

  • 您可以使任何线程调用 incrementAndGet(),因此可以使线程奇数"打印,第一个是奇数,第二个是偶数.
  • 您可以让第一个线程循环打印数字,看看条件是否再次满足(因为第二个线程再次将 chk 设置为 true ,然后打印,所有这些都在第二个线程之前有机会打印).
  • 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.
  • 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).

如您所见,要获得所需的结果,必须原子完成以下操作:

As you can see, to achieve the result you want, you must have the following operations done atomically:

  • compareAndSet()布尔值
  • incrementAndGet()数字
  • 打印

如果这3个操作不是原子操作,则可以安排线程以任何可能的顺序运行这些操作,而您无法控制输出.最简单的方法是使用同步块:

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. 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 }
    }
}

这篇关于java:使用2个线程打印奇数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆