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