Как проверить, истинны ли множественные «неправильные» логические значения? - PullRequest
0 голосов
/ 04 ноября 2018

У меня есть несколько * телефонных пунктов под ArrayList: thePhones, типа данных PhoneX1.

.moved() возвращает true при перемещении телефона.

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

Приведенный выше код успешно работает, ожидая перемещения итерации aPhone и выводя то, что ожидается. Однако я хотел бы, чтобы программа выяснила, когда перемещается неправильный телефон, чей номер не равен aPhone, чтобы программа могла выводить что-то вроде: «Неправильный телефон перемещен, Программа завершена». и прекратить. Например, если первый телефон в thePhones является ожидаемым для перемещения , но перемещается любой другой телефон, программа должна завершить работу.

Упомянутые телефоны являются старыми iPhone.

Ответы [ 3 ]

0 голосов
/ 04 ноября 2018

Я бы хотел, чтобы программа выяснила, когда перемещается неправильный телефон, который не равен aPhone, чтобы программа могла выводить что-то вроде: "Неправильный телефон перемещен

Ваш aPhone здесь на самом деле является коллекцией типа PhoneX1, поэтому неясно, как вы получаете то, что не соответствует универсальному типу вашей коллекции.

Телефоны, о которых идет речь, являются старыми iPhone.

я предпочел бы, чтобы в вашем классе PhoneX1 была включена логическая переменная, скажем

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"));
0 голосов
/ 04 ноября 2018

Если я правильно понял задачу, то вы в основном хотите «отслеживать» движения телефона и считать это ошибкой, если они не перемещены в правильном порядке. Это означает, что вам придется отслеживать состояние каждого телефона в отдельности , предполагая, что состояние, возвращаемое методом 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
0 голосов
/ 04 ноября 2018

Вы можете использовать потоки внутри цикла while, чтобы сделать что-то вроде:

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

Что вернет true, если были перемещены другие телефоны в List:

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