您的位置:首页 > 编程语言 > Java开发

Java高并发编程-生产者消费者问题

2018-02-07 12:32 676 查看

生产者消费者模型

思路一

通过实际问题构造一个生产者和消费者问题,用馒头类,放馒头的框,生产馒头的厨师类,和吃馒头的消费者类,其中后两者实现Runnable接口,然后通过创建多个线程来生产馒头和消费馒头;

代码实现一

public class Main {
public static void main(String[] args) {
Bucket b = new Bucket(6);
Producer p = new Producer(b);
Consumer c = new Consumer(b);
new Thread(p).start();
new Thread(c).start();

}
}

class Mantou {
@Override
public String toString() {
return "Mantou:" + id;
}
int id;
Mantou(int id) {
this.id = id;
}
}

class Bucket {
int max, index;
Mantou[] m;
Bucket(int max) {
this.max = max;
index = -1;
m = new Mantou[max];
}

synchronized void push(Mantou m1) {
while (index == max-1) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

this.notify();
m[++ index] = m1;
}

synchronized Mantou pop() {
while (index == -1) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

this.notify();
return m[index --];
}

}

class Producer implements Runnable {
Bucket b = null;
Producer(Bucket b) {
this.b = b;
}
@Override
public void run() {
for (int i=0; i<20; i++) {
Mantou m = new Mantou(i);
System.out.println("生产了:" + m);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
b.push(m);
}
}
}

class Consumer implements Runnable {
Bucket b = null;
Consumer(Bucket b) {
this.b = b;
}
@Override
public void run() {
for (int i=0; i<20; i++) {
Mantou m = b.pop();
System.out.println("消费了:" + m);
}
}
}


思路二

通过创建同步容器来模拟生产者和消费者的
be8f
问题;

代码实现二

package useful;

import java.util.ArrayList;
import java.util.List;

public class MyContainer<T> {

private final int max = 10;
private final List<T> list = new ArrayList<>();
//  private int count = 0;

synchronized void put(T t) {
while (list.size() == max) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
list.add(t);
//      count ++;
}

synchronized T get() {
while (list.size() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
//      count --;
return list.remove(list.size()-1);
}

public static void main(String[] args) {
MyContainer<String> m = new MyContainer<>();

for (int i=0; i<10; i++) {
new Thread(() -> {
for (int j=0; j<5; j++) System.out.println(Thread.currentThread().getName() + " consumed " + m.get());
}, "c" + i).start();;
}

for (int i=0; i<10; i++) {
new Thread(() -> {
for (int j=0; j<5; j++) {
m.put(Thread.currentThread().getName() + ":" + j);
}
}, "p" + i).start();;
}
}

}


思路三

利用Lock和Condition实现并发访问;可以精确控制到让哪一个或者哪一种线程唤醒;

代码如下

package useful;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyContainer<T> {

private final int max = 10;
private final List<T> list = new ArrayList<>();
Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition();

void put(T t) {
try {
lock.lock();
while (list.size() == max) {
producer.await();
}
list.add(t);
consumer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}

synchronized T get() {
T t = null;
try {
lock.lock();
while (list.size() == 0) {
consumer.await();
}
t = list.get(list.size()-1);
producer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return t;
}

public static void main(String[] args) {
MyContainer<String> m = new MyContainer<>();

for (int i=0; i<10; i++) {
new Thread(() -> {
for (int j=0; j<5; j++) System.out.println(Thread.currentThread().getName() + " consumed " + m.get());
}, "c" + i).start();;
}

for (int i=0; i<10; i++) {
new Thread(() -> {
for (int j=0; j<5; j++) {
m.put(Thread.currentThread().getName() + ":" + j);
}
}, "p" + i).start();;
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: