首先实现一个队列
public class ArrayQueue {
private int[] array = new int[10];
private int size = 0;
private int front = 0;
private int rear = 0;
public void put(int val){
if(size == array.length){
throw new RuntimeException("队列已满");
}
array[rear++] = val;
if(rear == array.length){
rear = 0;
}
size++;
}
public int take(){
if(size == 0){
throw new RuntimeException("队列空");
}
int val = array[front];
front = (front+1)%array.length;
size--;
return val;
}
public int getSize(){
return size;
}
生产者、消费者模型
private static ArrayQueue queue = new ArrayQueue();
private static class Producer extends Thread {
Producer(){
super("生产者");
}
PrintWriter printWriter;
{
try {
printWriter = new PrintWriter("生产了.txt", "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
Random random = new Random(20191216);
for (int i = 0; i < 5000; i++) {
int val = random.nextInt(100);
System.out.println(val);
printWriter.println(val);
do {
try {
queue.put(val);
break;
} catch (RuntimeException e) {
}
}while (true);
}
printWriter.close();
}
}
private static class Customer extends Thread{
Customer(){
super("消费者");
}
PrintWriter printWriter;
{
try {
printWriter = new PrintWriter("消费了.txt","UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
for (int i = 0; i < 5000; i++) {
do {
try {
int val = queue.take();
printWriter.println(val);
break;
} catch (RuntimeException e) {
}
}while (true);
}
printWriter.close();
}
}
public static void main(String[] args) {
Producer producer = new Producer();
producer.start();
Customer customer = new Customer();
customer.start();
}
上述模型初始形态:
1.创建生产者、消费者类并集成线程,通过Thread的构造方法命名两个线程;
2.通过PrintWriter将生产的元素和消费的元素写到文本中用于比对;
3.复写run()方法,一个调用put进行生产,一个调用take()进行消费;
单生产者、单消费者
private int[] array = new int[10];
private volatile int size = 0;
private int front = 0;
private int rear = 0;
public void put(int val) throws InterruptedException {
if(size == array.length){
synchronized (this){
wait();
}
}
array[rear++] = val;
if(rear == array.length){
rear = 0;
}
synchronized (this) {
size++;
notify();
}
}
public int take() throws InterruptedException {
if(size == 0){
synchronized (this){
wait();
}
}
int val = array[front];
front = (front+1)%array.length;
synchronized (this) {
size--;
notify();
}
return val;
}
public int getSize(){
return size;
}
private static ArrayQueue queue = new ArrayQueue();
private static class Producer extends Thread {
Producer(){
super("生产者");
}
@Override
public void run() {
Random random = new Random(20191216);
for (int i = 0; i < 5000; i++) {
int val = random.nextInt(100);
try {
queue.put(val);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class Customer extends Thread{
Customer(){
super("消费者");
}
@Override
public void run() {
for (int i = 0; i < 5000; i++) {
try {
int val = queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Producer producer = new Producer();
producer.start();
Customer customer = new Customer();
customer.start();
}
实现生产者、消费者模型的线程安全:
1、用volatile保证线程安全
2、size0或sizearray.length时调用wait()方法,使线程进入等待集
3、当size++或size–时通过synchronize锁住类,并且notify唤醒生产者或消费者,保证线程安全
**但是多消费者或多生产者时线程不安全;
最终版
private int[] array = new int[10];
private volatile int size = 0;
private int front = 0;
private int rear = 0;
public synchronized void put(int val) throws InterruptedException {
while (size == array.length){
wait();
}
array[rear++] = val;
if(rear == array.length){
rear = 0;
}
synchronized (this) {
size++;
notifyAll();
}
}
public synchronized int take() throws InterruptedException {
while (size == 0){
wait();
}
int val = array[front];
front = (front+1)%array.length;
synchronized (this) {
size--;
notifyAll();
}
return val;
}
public int getSize(){
return size;
}
private static ArrayQueue queue = new ArrayQueue();
private static class Producer extends Thread {
Producer(){
super("生产者");
}
@Override
public void run() {
Random random = new Random(20191216);
while (true){
int val = random.nextInt(100);
try {
queue.put(val);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class Customer extends Thread{
Customer(){
super("消费者");
}
@Override
public void run() {
while (true){
try {
int val = queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Producer producer = new Producer();
producer.start();
for (int i = 0; i < 3; i++) {
Customer customer = new Customer();
customer.start();
}
while (producer.isAlive()){
System.out.println(ArrayQueue.queue.getSize());
TimeUnit.MILLISECONDS.sleep(1);
}
}
1、在take()和put()方法上加synchronize
2、用while()语句判断size的值
3、调用notifyAll唤醒所有线程
原因:
1、当消费者和生产者线程都进入等待集,唤醒是随机的故要加notifyAll,while()用也在此
2、synchronize防止while语句判断完后被抢CUP导致线程不安全;