多线程,这属于典型的Producer/Consumer 问题The Producer/Consumer Example
The Producer generates an integer between 0 and 9 (inclusive), stores it in a CubbyHole object, and prints the generated number. To make the synchronization problem more interesting, the Producer sleeps for a random amount of time between 0 and 100 milliseconds before repeating the number generating cycle:
public class Producer extends Thread {
private CubbyHole cubbyhole;
private int number; public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
} public void run() {
for (int i = 0; i < 10; i++) {
cubbyhole.put(i);
System.out.println("Producer #" + this.number
+ " put: " + i);
try {
sleep((int)(Math.random() * 100));
} catch (InterruptedException e) { }
}
}
}The Consumer, being ravenous, consumes all integers from the CubbyHole (the exact same object into which the Producer put the integers in the first place) as quickly as they become available.
public class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number; public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
} public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = cubbyhole.get();
System.out.println("Consumer #" + this.number
+ " got: " + value);
}
}
}
The Producer and Consumer in this example share data through a common CubbyHole object. And you will note that neither the Producer nor the Consumer makes any effort whatsoever to ensure that the Consumer is getting each value produced once and only once. The synchronization between these two threads actually occurs at a lower level, within the get and put methods of the CubbyHole object. However, let's assume for a moment that these two threads make no arrangements for synchronization and talk about the potential problems that might arise in that situation.
One problem arises when the Producer is quicker than the Consumer and generates two numbers before the Consumer has a chance to consume the first one. Thus the Consumer would skip a number. Part of the output might look like this: . . .Consumer #1 got: 3
Producer #1 put: 4
Producer #1 put: 5
Consumer #1 got: 5 . . .Another problem that might arise is when the Consumer is quicker than the Producer and consumes the same value twice. In this situation, the Consumer would print the same value twice and might produce output that looked like this:
. . .Producer #1 put: 4
Consumer #1 got: 4
Consumer #1 got: 4
Producer #1 put: 5 . . .Either way, the result is wrong. You want the Consumer to get each integer produced by the Producer exactly once. Problems such as those just described are called race conditions. They arise from multiple, asynchronously executing threads trying to access a single object at the same time and getting the wrong result.
Race conditions in the producer/consumer example are prevented by having the storage of a new integer into the CubbyHole by the Producer be synchronized with the retrieval of an integer from the CubbyHole by the Consumer. The Consumer must consume each integer exactly once. The activities of the Producer and Consumer must be synchronized in two ways. First, the two threads must not simultaneously access the CubbyHole. A Java thread can prevent this from happening by locking an object. When an object is locked by one thread and another thread tries to call a synchronized method on the same object, the second thread will block until the object is unlocked. Locking an Object discusses this. And second, the two threads must do some simple coordination. That is, the Producer must have some way to indicate to the Consumer that the value is ready and the Consumer must have some way to indicate that the value has been retrieved. The Thread class provides a collection of methods--wait, notify, and notifyAll--to help threads wait for a condition and notify other threads of when that condition changes. Using the notifyAll and wait Methods has more information. The Main Program
Here's a small stand-alone Java application that creates a CubbyHole object, a Producer, a Consumer, and then starts both the Producer and the Consumer.
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1); p1.start();
c1.start();
}
}The Output
Here's the output of ProducerConsumerTest.
Producer #1 put: 0
Consumer #1 got: 0
Producer #1 put: 1
Consumer #1 got: 1
Producer #1 put: 2
Consumer #1 got: 2
Producer #1 put: 3
Consumer #1 got: 3
Producer #1 put: 4
Consumer #1 got: 4
Producer #1 put: 5
Consumer #1 got: 5
Producer #1 put: 6
Consumer #1 got: 6
Producer #1 put: 7
Consumer #1 got: 7
Producer #1 put: 8
Consumer #1 got: 8
Producer #1 put: 9
Consumer #1 got: 9public synchronized int get() {
while (available == false) {
try {
// wait for Producer to put value
wait();
} catch (InterruptedException e) {
}
}
available = false;
// notify Producer that value has been retrieved
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
// wait for Consumer to get value
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
// notify Consumer that value has been set
notifyAll();
}
The Producer generates an integer between 0 and 9 (inclusive), stores it in a CubbyHole object, and prints the generated number. To make the synchronization problem more interesting, the Producer sleeps for a random amount of time between 0 and 100 milliseconds before repeating the number generating cycle:
public class Producer extends Thread {
private CubbyHole cubbyhole;
private int number; public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
} public void run() {
for (int i = 0; i < 10; i++) {
cubbyhole.put(i);
System.out.println("Producer #" + this.number
+ " put: " + i);
try {
sleep((int)(Math.random() * 100));
} catch (InterruptedException e) { }
}
}
}The Consumer, being ravenous, consumes all integers from the CubbyHole (the exact same object into which the Producer put the integers in the first place) as quickly as they become available.
public class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number; public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
} public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = cubbyhole.get();
System.out.println("Consumer #" + this.number
+ " got: " + value);
}
}
}
The Producer and Consumer in this example share data through a common CubbyHole object. And you will note that neither the Producer nor the Consumer makes any effort whatsoever to ensure that the Consumer is getting each value produced once and only once. The synchronization between these two threads actually occurs at a lower level, within the get and put methods of the CubbyHole object. However, let's assume for a moment that these two threads make no arrangements for synchronization and talk about the potential problems that might arise in that situation.
One problem arises when the Producer is quicker than the Consumer and generates two numbers before the Consumer has a chance to consume the first one. Thus the Consumer would skip a number. Part of the output might look like this: . . .Consumer #1 got: 3
Producer #1 put: 4
Producer #1 put: 5
Consumer #1 got: 5 . . .Another problem that might arise is when the Consumer is quicker than the Producer and consumes the same value twice. In this situation, the Consumer would print the same value twice and might produce output that looked like this:
. . .Producer #1 put: 4
Consumer #1 got: 4
Consumer #1 got: 4
Producer #1 put: 5 . . .Either way, the result is wrong. You want the Consumer to get each integer produced by the Producer exactly once. Problems such as those just described are called race conditions. They arise from multiple, asynchronously executing threads trying to access a single object at the same time and getting the wrong result.
Race conditions in the producer/consumer example are prevented by having the storage of a new integer into the CubbyHole by the Producer be synchronized with the retrieval of an integer from the CubbyHole by the Consumer. The Consumer must consume each integer exactly once. The activities of the Producer and Consumer must be synchronized in two ways. First, the two threads must not simultaneously access the CubbyHole. A Java thread can prevent this from happening by locking an object. When an object is locked by one thread and another thread tries to call a synchronized method on the same object, the second thread will block until the object is unlocked. Locking an Object discusses this. And second, the two threads must do some simple coordination. That is, the Producer must have some way to indicate to the Consumer that the value is ready and the Consumer must have some way to indicate that the value has been retrieved. The Thread class provides a collection of methods--wait, notify, and notifyAll--to help threads wait for a condition and notify other threads of when that condition changes. Using the notifyAll and wait Methods has more information. The Main Program
Here's a small stand-alone Java application that creates a CubbyHole object, a Producer, a Consumer, and then starts both the Producer and the Consumer.
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1); p1.start();
c1.start();
}
}The Output
Here's the output of ProducerConsumerTest.
Producer #1 put: 0
Consumer #1 got: 0
Producer #1 put: 1
Consumer #1 got: 1
Producer #1 put: 2
Consumer #1 got: 2
Producer #1 put: 3
Consumer #1 got: 3
Producer #1 put: 4
Consumer #1 got: 4
Producer #1 put: 5
Consumer #1 got: 5
Producer #1 put: 6
Consumer #1 got: 6
Producer #1 put: 7
Consumer #1 got: 7
Producer #1 put: 8
Consumer #1 got: 8
Producer #1 put: 9
Consumer #1 got: 9public synchronized int get() {
while (available == false) {
try {
// wait for Producer to put value
wait();
} catch (InterruptedException e) {
}
}
available = false;
// notify Producer that value has been retrieved
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
// wait for Consumer to get value
wait();
} catch (InterruptedException e) {
}
}
contents = value;
available = true;
// notify Consumer that value has been set
notifyAll();
}
解决方案 »
- java.sql.SQLException: Column not found 错误怎么处理
- 代码编译出错,求助!
- j2se,j2ee,j2me 中配置文件用哪种的好?
- short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)
- JAVA Frame里点一个按钮后,怎么弹出一个新的窗体?
- java类中用构造方法赋值,用成员方法获得相应值
- [??在线等]关于参数传递!急!希望大家帮忙!
- java中怎样实现象C++中一样使用print输出格式,如print("%ld",i)
- 请教错在哪里?
- 本人需要写一个在网页上运行的Applet调用DLL的程序,不知道哪位有资料,可否给个介绍!
- websphere性能调整的一些体会和一些还不是很明白的问题
- 谁知道WROX?
如果未获得,则读操作自动阻塞直到数据到来。
流式通信本来就是这样的阿。