- bawangyxw
- 等级:


- 性别:
 - 文章: 22
- 积分: 140
- 来自: 武汉

|
编写一段生产者/消费者的Java代码,其中生产者每次生产1个0到1000之间的随机数,消费者则把该随机数打印出来。如果产生的随机数为0,则生产者、消费者均退出运行。要求生产者、消费者均使用线程来实现。如题,线程基本的我也会,但是像这样有点复杂的还真不会,求大家帮我啊
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
返回顶楼 |
|
|
- xiangyaoan
- 等级: 初级会员

- 性别:
 - 文章: 2
- 积分: 30
- 来自: 湖南

|
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
private static List<Integer> memory = new ArrayList<Integer>();
private static boolean flag = true;
private static int memoryLength;
public static void main(String[] args) {
Thread thread_product = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("product-start");
while (flag) {
int num = new Random().nextInt(1000);
memory.add(num);
if(num == 0){
flag = false;
}
}
System.out.println("product-complete");
}
},"thread-product");
Thread thread_client = new Thread(new Runnable() {
@Override
public void run() {
while (flag || memory.size() != memoryLength) {
if(flag && memory.size()==memoryLength){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("client:"+memory.get(memoryLength++));
}
System.out.println("client-complete");
}
},"thread-client");
thread_product.start();
thread_client.start();
}
}
这样行吗?
|
返回顶楼 |
|
|
- dohkoos
- 等级:


- 文章: 238
- 积分: 236
- 来自: 北京

|
xiangyaoan 写道
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
private static List<Integer> memory = new ArrayList<Integer>();
private static boolean flag = true;
...
},"thread-client");
thread_product.start();
thread_client.start();
}
}
这样行吗?
很不幸,你的代码没有考虑同步问题
|
返回顶楼 |
|
|
- OpenMind
- 等级:


- 性别:
 - 文章: 52
- 积分: 170
- 来自: 深圳

|
为什么要重复造车轮,不直接使用java.util.concurrent.BlockingQueue?
|
返回顶楼 |
|
|
- arthur8
- 等级: 初级会员

- 性别:
 - 文章: 8
- 积分: 30
- 来自: 北京

|
OpenMind 写道 为什么要重复造车轮,不直接使用java.util.concurrent.BlockingQueue?
对,直接使用ArrayBlockingQueue或者LinkedBlockingQueue
|
返回顶楼 |
|
|
- moonights
- 等级: 初级会员

- 性别:
 - 文章: 19
- 积分: 60
- 来自: 北京

|
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class BlockingQueueTest {
private static String FLAG="99";
public static class Basket {
// 篮子,能够容纳1000个数字
BlockingQueue<String> basket = new LinkedBlockingQueue<String>(1000);
// 生产数字,放入篮子
public String produce() throws InterruptedException {
int num = new Random().nextInt(1000);
System.out.println("++放入篮子中一个数字:"+num );
basket.put(num+"");
return num+"";
}
// 消费数字,从篮子中取走
public String consume() throws InterruptedException {
String num=basket.take();
System.out.println("--取出篮子中一个数字:"+num );
return num;
}
}
// 测试方法
public static void testBasket() {
final Basket basket = new Basket();
// 定义生产者
class Producer implements Runnable {
public void run() {
try {
while (true) {
if(basket.produce().equals(FLAG)){
System.out.println("!成功生产正确数字:"+FLAG);
break;
}
// 休眠300ms
Thread.sleep(300);
}
} catch (InterruptedException ex) {
}
}
}
// 定义数字消费者
class Consumer implements Runnable {
public void run() {
try {
while (true) {
// 消费数字
// 休眠1000ms
if(basket.consume().equals(FLAG)){
System.out.println("!成功获取正确数字:"+FLAG);
break;
}
Thread.sleep(500);
}
} catch (InterruptedException ex) {
}
}
}
ExecutorService service = Executors.newCachedThreadPool();
Producer producer = new Producer();
Consumer consumer = new Consumer();
service.submit(producer);
service.submit(consumer);
// 程序运行60s后,所有任务停止
try {
Thread.sleep(60*1000);
} catch (InterruptedException e) {
}
service.shutdownNow();
}
public static void main(String[] args) {
BlockingQueueTest.testBasket();
}
}
|
返回顶楼 |
|
|
- white_crucifix
- 等级:


- 性别:
 - 文章: 230
- 积分: 110
- 来自: 杭州

|
发表时间:2013-10-09
最后修改:2013-10-09
给出一个更贴近考题细节的答案。
几点注意: 1. 消费生产者模式原则上讲究生产一个产品后就不能再生产,要等消费完才能生产第二个。因此可以选用SynchronousQueue。当然广义上的消费生产者,用BlockingQueue旗下的任意一个实现类都可以。
2.逻辑很简单,一个线程往queue里存(put),一个线程从queue里取(take)。put和take都是阻塞型的方法,防止while循环死命的循环下去。
3. 随机出0后,producer和consumer都必须停止,如果不用threadpool工具来做,单纯用thread来实现,就要注意,让thread在合适的时候return。比如生产者随机到0时,return并且依然把0存入queue,消费者取出0时,线程return。
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
public class Test {
BlockingQueue<Integer> queue = new SynchronousQueue<Integer>();
Random rd = new Random();
class Producer extends Thread {
@Override
public void run() {
while (true) {
int number = rd.nextInt(1000);
System.out.println("Producer Generate : " + number);
try {
queue.put(number);
if (number == 0) {
System.out.println("Producer stoped.");
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
@Override
public void run() {
while (true) {
try {
if (queue.take() == 0) {
System.out.println("Consumer stoped.");
return;
}
;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void startTest() {
Producer producer = new Producer();
Consumer consumer = new Consumer();
producer.start();
consumer.start();
}
public static void main(String[] args) {
new Test().startTest();
}
}
|
返回顶楼 |
|
|
- lvwenwen
- 等级: 初级会员

- 性别:
 - 文章: 913
- 积分: 50
- 来自: 魔都

|
OpenMind 写道 为什么要重复造车轮,不直接使用java.util.concurrent.BlockingQueue?
为什么要重复造车轮,不直接使用java.util.concurrent.BlockingQueue?
|
返回顶楼 |
|
|
- bawangyxw
- 等级:


- 性别:
 - 文章: 22
- 积分: 140
- 来自: 武汉

|
谢谢各位的回复,昨天有位师傅指导,我也写了个
package cn.yxw.test;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadTest {
/**
* @param args
*/
public static void main(String[] args) {
Storage storage = new Storage();
new Producer(storage).start();
new Customer(storage).start();
}
}
class Customer extends Thread {
private Storage storage;
public Customer(Storage storage) {
this.storage = storage;
}
public void run() {
while (true) {
try {
if (Storage.NUM == 0) {
System.out.println("打印:" + 0 + ",线程终止");
break;
}
Integer num = storage.print();
System.out.println("打印:" + num);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread {
private Storage storage;
public Producer(Storage storage) {
this.storage = storage;
}
public void run() {
while (true) {
try {
Integer num = new Random().nextInt(1000);
Storage.NUM = num;
if (Storage.NUM == 0) {
System.out.println("生产:" + 0 + ",线程终止");
break;
}
storage.put(num);
System.out.println("生产:" + num);
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Storage {
private BlockingQueue<Integer> randomData = new ArrayBlockingQueue<Integer>(
1);// 空间大小为1的阻塞队列
public static int NUM = -1;
public void put(Integer number) {
try {
randomData.put(number);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int print() {
try {
Integer number = randomData.take();
return number;
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
}
|
返回顶楼 |
|
|
- white_crucifix
- 等级:


- 性别:
 - 文章: 230
- 积分: 110
- 来自: 杭州

|
恩,看了一下,我和你的代码逻辑基本是一样的。 另外,两点拙见: 一个是// 空间大小为1的阻塞队列,其实就是SynchronousQueue,jdk为这个特性量身定做的数据结构。ArrayQueue往往用来做缓存队列。 另一个就是建议Random实例放在全局,只需一个,不然每次循环都new一次,内存有点浪费
|
返回顶楼 |
|
|