如何检查是否有多个“错误的”布尔值正确?

时间:2018-11-04 02:59:44

标签: java multithreading for-loop while-loop boolean

ArrayListthePhones下,我有许多* phone项,数据类型为PhoneX1

移动电话时,

.moved()返回true

for (PhoneX1 aPhone : thePhones) {
    while (!aPhone.moved()) {
        Thread.sleep(1000);
    } 
    System.out.println(aPhone + " Moved")
    ...

上面的代码通过等待aPhone被迭代移动并输出期望的内容而成功工作。但是,我希望该程序找出何时移动了不等于aPhone的错误电话,以便该程序可以输出以下内容:“移动了错误的电话,程序已终止”,然后终止。例如,如果thePhones中的第一个电话被移动了 expected ,但其他任何电话被移动了,则程序应终止。

所引用的电话是旧的iPhone。

3 个答案:

答案 0 :(得分:2)

您可以在while循环中使用流来执行以下操作:

thePhones.stream().filter(e -> !e.equals(aPhone)).anyMatch(PhoneX1::moved)

如果List中的任何其他电话已被移动,则哪个将返回true:

while (!aPhone.moved()) {
    if(thePhones.stream().filter(e -> !e.equals(aPhone)).anyMatch(PhoneX1::moved)) {
       //Do something
    }
    Thread.sleep(1000);
}  

答案 1 :(得分:2)

如果我正确地理解了该任务,那么您基本上想“监视”电话机芯,并在未按正确顺序移动它们时将其视为错误。这意味着,假设moved()方法返回的状态可能随时更改,则必须分别监视每个电话的状态。

如果这是正确的,则一种方法是:

  • 定义要移动的手机的预期顺序(这是列表中的顺序)
  • 为每部手机安排一个任务,以监视手机的状态
  • 如果任务检测到手机已移动,请将其放入(阻止)队列中
  • 等待将每个电话放入队列中,并验证它们是否按预期顺序出现在该队列中

在这里实现,以显示基本思想。可能会有警告,具体取决于轮询频率等,但我认为这可能是一种合理的方法。但是,也可以使用其他实现方式(例如,使用ExecutorCompletionService

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;

public class PhoneMoveDetector
{
    // Dummy phone class that changes its "moved()" state after a certain time
    private static class PhoneX1
    {
        private final String name;
        private volatile boolean moved = false;

        PhoneX1(String name, long delayMs)
        {
            this.name = name;
            Thread t = new Thread(() -> 
            {
                try
                {
                    Thread.sleep(delayMs);
                }
                catch (InterruptedException e)
                {
                    Thread.currentThread().interrupt();
                }
                System.out.println("Moving " + this);
                moved = true;
            });
            t.start();
        }

        boolean moved()
        {
            return moved;
        }

        @Override
        public String toString()
        {
            return name;
        }
    }

    public static void main(String[] args)
    {
        checkRightMoveOrder();
        detectWrongMoveOrder();
    }

    private static void checkRightMoveOrder()
    {
        List<PhoneX1> phones = new ArrayList<PhoneX1>();
        phones.add(new PhoneX1("A", 1500));
        phones.add(new PhoneX1("B", 3000));
        phones.add(new PhoneX1("C", 4500));
        phones.add(new PhoneX1("D", 6000));

        MoveDetector moveDetector = new MoveDetector(phones);

        System.out.println("Checking right move order");
        for (PhoneX1 phone : phones)
        {
            try
            {
                moveDetector.waitForExpectedToMove();
            }
            catch (InterruptedException e)
            {
                Thread.currentThread().interrupt();
                return;
            }
            System.out.println("Moved " + phone);
        }
    }

    private static void detectWrongMoveOrder()
    {
        List<PhoneX1> phones = new ArrayList<PhoneX1>();
        phones.add(new PhoneX1("A", 1500));
        phones.add(new PhoneX1("B", 3000));
        phones.add(new PhoneX1("C", 2000)); // Should be moved later
        phones.add(new PhoneX1("D", 6000));

        MoveDetector moveDetector = new MoveDetector(phones);

        System.out.println("Detecting wrong move order");
        for (PhoneX1 phone : phones)
        {
            try
            {
                moveDetector.waitForExpectedToMove();
            }
            catch (InterruptedException e)
            {
                Thread.currentThread().interrupt();
                return;
            }
            System.out.println("Moved " + phone);
        }
    }


    private static class MoveDetector
    {
        private final Queue<PhoneX1> expectedPhones;
        private final BlockingQueue<PhoneX1> movedPhones;

        MoveDetector(List<PhoneX1> phones)
        {
            expectedPhones = new LinkedList<PhoneX1>(phones);
            movedPhones = new LinkedBlockingDeque<PhoneX1>();
            ExecutorService executor = Executors.newCachedThreadPool();
            List<Callable<Object>> observers = 
                new ArrayList<Callable<Object>>();
            for (PhoneX1 phone : phones)
            {
                Runnable r = () ->
                {
                    while (!phone.moved())
                    {
                        try
                        {
                            Thread.sleep(50);
                        }
                        catch (InterruptedException e)
                        {
                            Thread.currentThread().interrupt();
                            return;
                        }
                    }
                    movedPhones.offer(phone);
                };
                observers.add(Executors.callable(r));
            }
            Thread t = new Thread(() -> 
            {
                try
                {
                    executor.invokeAll(observers);
                    executor.shutdownNow();
                }
                catch (InterruptedException e1)
                {
                    Thread.currentThread().interrupt();
                }
            });
            t.start(); 
        }

        void waitForExpectedToMove() throws InterruptedException
        {
            PhoneX1 moved = movedPhones.take();
            PhoneX1 expected = expectedPhones.peek();
            if (!Objects.equals(expected, moved))
            {
                System.out.println("Moved " + moved + ", but expected " 
                    + expected + " - ERROR!");
                // Handle this case as desired, e.g. by doing a
                // throw new IllegalStateException();
            }
            else
            {
                System.out.println("Moved " + moved + ", as expected");
                expectedPhones.remove();
            }
        }
    }
}

输出显示在这里:

Checking right move order
Moving A
Moved A, as expected
Moved A
Moving B
Moved B, as expected
Moved B
Moving C
Moved C, as expected
Moved C
Moving D
Moved D, as expected
Moved D

Detecting wrong move order
Moving A
Moved A, as expected
Moved A
Moving C
Moved C, but expected B - ERROR!
Moved B
Moving B
Moved B, as expected
Moved C
Moving D
Moved D, but expected C - ERROR!
Moved D

答案 2 :(得分:0)

  

我希望程序找出移动不正确的电话(不等于aPhone)的时间,以便程序可以输出以下内容:“移动了错误的电话

这里的aPhone实际上是PhoneX1类型的集合,因此尚不清楚如何获得与集合的通用类型不匹配的东西。

  

所引用的电话是旧的iPhone。

我的建议是,您的类PhoneX1包含一个布尔变量say

bool isOldIphone = false;

然后从您的驱动程序中检查电话的类型(旧的还是新的)并执行逻辑操作

ArrayList<PhoneX1> oldPhones = thePhones.stream().filter(e -> e.isOldIphone);     //this returns a list of old phones

然后您可以继续执行说出的逻辑

oldPhones.forEach(System.out.println("old phone moved"));