Блокирование Очереди - Потребность больше информации

Одним словом, вы не можете.

3.65 нельзя представить в точности как float. Число, которое вы получаете, является ближайшим к 3.65 числом, которое имеет точное представление float.

Разница между (более старым?) Python 2 и 3 обусловлена ​​форматированием по умолчанию.

Я вижу следующее как в Python 2.7.3, так и в 3.3.0:

In [1]: 3.65
Out[1]: 3.65

In [2]: '%.20f' % 3.65
Out[2]: '3.64999999999999991118'

Точный тип данных в десятичном формате см. В decimal.Decimal .

5
задан Community 23 May 2017 в 12:06
поделиться

3 ответа

Вы добавляли с помощью add , offer или put ? Я предполагаю, что вы использовали add , поскольку только он может вызвать исключение IllegalStateException ; но если вы прочитаете таблицу , вы увидите, что если вам нужна семантика блокировки, вы должны использовать put take для удаления).

Edit: В вашем примере есть пара проблем.

Сначала я отвечу на вопрос «Почему не вставляется E, когда я вызываю take () в первый раз? " Ответ заключается в том, что к моменту вызова take () вы уже попытались и не смогли вставить E. После освобождения пространства вставлять нечего.

Теперь, если вы изменили offer () на put () , put («E») никогда не вернется. Зачем? Потому что он ожидает, пока какой-то другой поток удалит элемент из очереди. Помните, что BlockingQueues предназначены для доступа к нескольким потокам. Блокировка бесполезна (на самом деле хуже, чем бесполезна), если у вас однопотоковое приложение.

Вот улучшенный пример:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}

Теперь вызов put ("E") действительно будет успешным, поскольку теперь он может ждать, пока потребительский поток не удалит «A» из очереди. Последний take () по-прежнему будет блокироваться бесконечно, поскольку нет шестого элемента, который нужно удалить.

ожидает, пока какой-то другой поток удалит элемент из очереди. Помните, что BlockingQueues предназначены для доступа к нескольким потокам. Блокировка бесполезна (на самом деле хуже, чем бесполезна), если у вас однопотоковое приложение.

Вот улучшенный пример:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}

Теперь вызов put ("E") действительно будет успешным, поскольку теперь он может ждать, пока потребительский поток не удалит «A» из очереди. Последний take () по-прежнему будет блокироваться бесконечно, поскольку нет шестого элемента, который нужно удалить.

ожидает, пока какой-то другой поток удалит элемент из очереди. Помните, что BlockingQueues предназначены для доступа к нескольким потокам. Блокировка бесполезна (на самом деле хуже, чем бесполезна), если у вас однопотоковое приложение.

Вот улучшенный пример:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}

Теперь вызов put ("E") действительно будет успешным, поскольку теперь он может ждать, пока потребительский поток не удалит «A» из очереди. Последний take () по-прежнему будет блокироваться бесконечно, поскольку нет шестого элемента, который нужно удалить.

Вот улучшенный пример:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}

Теперь вызов put ("E") действительно будет успешным, так как теперь он может ждать, пока поток потребителя удалит "A" из очереди. Последний take () по-прежнему будет блокироваться бесконечно, поскольку нет шестого элемента, который нужно удалить.

Вот улучшенный пример:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}

Теперь вызов put ("E") действительно будет успешным, так как теперь он может ждать, пока поток потребителя удалит "A" из очереди. Последний take () по-прежнему будет блокироваться бесконечно, поскольку нет шестого элемента, который нужно удалить.

11
ответ дан 18 December 2019 в 13:18
поделиться

ммайерс опередил меня: P (+1)
это должно быть то, что вам нужно, удачи!

ПРИМЕЧАНИЕ: put () завершится ошибкой в ​​вашем примере, потому что put () будет блокироваться до тех пор, пока не освободится место. Поскольку пространство никогда не доступно, программа никогда не продолжает выполнение.

==== старый ответ ======

BlockingQueue - это интерфейс, вам придется использовать один из реализующих классов.

] "Характер блокировки" просто указывает, что вы можете запросить что-то из своей очереди, и если она пуста, поток, в котором она находится, будет блокировать (ждать), пока что-то не будет добавлено в очередь, а затем продолжит обработку .

ArrayBlockingQueue
DelayQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

//your main collection
LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<Integer>();

//Add your values
lbq.put(100);
lbq.put(200);

//take() will actually remove the first value from the collection, 
//or block if no value exists yet.
//you will either have to interrupt the blocking, 
//or insert something into the queue for the program execution to continue

int currVal = 0;
try {
    currVal = lbq.take();
} catch (InterruptedException e) {
    e.printStackTrace();
}

2
ответ дан 18 December 2019 в 13:18
поделиться

Чтобы конкретно ответить на ваш вопрос: предложение - это неблокирующий вызов предложения, поэтому в однопоточном методе, подобном опубликованному вами, вызов предложения ('E') просто возвращает false без изменения полная очередь. Если вы использовали блокирующий вызов put ('E'), он будет спать, пока не освободится место. Навсегда в вашем простом примере. Вам потребуется отдельный поток для чтения из очереди, чтобы освободить место для завершения операции размещения.

1
ответ дан 18 December 2019 в 13:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: