1、wait/notify的方式
public class ConsumerProducter {
private static LinkedList<Object> mList = new LinkedList<>();
private static final int MAX = 10;
public static void main(String[] args) {
new Thread(new ProducterRunnable()).start();
new Thread(new ConsumerRunnable()).start();
}
/**
* 生产者
*/
private static class ProducterRunnable implements Runnable {
@Override
public void run() {
while (true) {
synchronized (mList) {
try {
if (mList.size() == MAX) {
//当生产者生产容器已经满,阻塞生产
mList.wait();
}
Object obj = new Object();
mList.add(obj);
System.out.println("Producter create one obj");
Thread.sleep(2000);
mList.notify();
} catch (Exception e) {
}
}
}
}
}
/**
* 消费者
*/
private static class ConsumerRunnable implements Runnable {
@Override
public void run() {
while (true) {
synchronized (mList) {
try {
if (mList.size() == 0) {
mList.wait();
}
mList.removeLast();
System.out.println("Consumer remove one obj");
mList.notify();
Thread.sleep(2000);
} catch (Exception e) {
}
}
}
}
}
}
2、显示锁/Condition
public class ConsumerProducter {
private static LinkedList<Object> mList = new LinkedList<>();
private static final int MAX = 10;
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public static void main(String[] args) {
new Thread(new ProducterRunnable()).start();
new Thread(new ConsumerRunnable()).start();
}
/**
* 生产者
*/
private static class ProducterRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
lock.lock();
if (mList.size() == MAX) {
condition.await();
}
System.out.println("producter create one obj ,now size is : " + mList.size());
mList.add(new Object());
condition.signal();
Thread.sleep(1000);
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
}
/**
* 消费者
*/
private static class ConsumerRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
lock.lock();
if (mList.size() == 0) {
condition.await();
}
mList.removeLast();
System.out.println("ConsumerRunnable remove one obj ,now size is : " + mList.size());
condition.signal();
Thread.sleep(1000);
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
}
}
3、使用阻塞队列
public class ConsumerProducter {
private static BlockingQueue<Object> blockingQueue = new LinkedBlockingQueue<>(10);
public static void main(String[] args) {
new Thread(new ProducterRunnable()).start();
new Thread(new ConsumerRunnable()).start();
}
/**
* 生产者
*/
private static class ProducterRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
blockingQueue.put(new Object());
System.out.println("Producter create one obj , size is : " + blockingQueue.size());
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 消费者
*/
private static class ConsumerRunnable implements Runnable {
@Override
public void run() {
while (true) {
try {
blockingQueue.take();
System.out.println("Consumer remove one obj ,size is : " + blockingQueue.size());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
4、IO管道
通过Java的IO管道流也可以实现类似生产者消费者模型的功能;
输入流相当于消费者,当read为-1时表示消费完了,阻塞;当in == out时表示生产已满。
public static void main(String[] args) throws IOException, InterruptedException {
new ThreadTest().start();
}
public class ThreadTest {
public void start() throws InterruptedException, IOException {
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedOutputStream.connect(pipedInputStream);
new Thread(new ReadRunnable(pipedInputStream)).start();
Thread.sleep(2000);
new Thread(new WriteRunnable(pipedOutputStream)).start();
}
private class ReadRunnable implements Runnable {
private PipedInputStream inputStream;
private ReadRunnable(PipedInputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public void run() {
try {
byte[] byteArray = new byte[20];
int readLength = inputStream.read(byteArray);
while (readLength != -1) {
String newData = new String(byteArray, 0, readLength);
System.out.println("read : " + newData);
readLength = inputStream.read(byteArray);
}
inputStream.close();
} catch (Exception e) {
}
}
}
private class WriteRunnable implements Runnable {
private PipedOutputStream outputStream;
private WriteRunnable(PipedOutputStream outputStream) {
this.outputStream = outputStream;
}
@Override
public void run() {
try {
for (int i = 0; i < 30; i++) {
String out = "" + i;
outputStream.write(out.getBytes());
System.out.println("write : " + out);
}
outputStream.close();
} catch (IOException e) {
}
}
}
/**
* 输出:
* write : 0
* write : 1
* write : 2
* write : 3
* write : 4
* write : 5
* write : 6
* write : 7
* write : 8
* write : 9
* write : 10
* write : 11
* write : 12
* write : 13
* write : 14
* write : 15
* write : 16
* write : 17
* write : 18
* write : 19
* write : 20
* write : 21
* write : 22
* write : 23
* write : 24
* write : 25
* write : 26
* write : 27
* write : 28
* write : 29
* read : 01234567891011121314
* read : 15161718192021222324
* read : 2526272829
*
* */
}