「java多消费」java多消费者问题
本篇文章给大家谈谈java多消费,以及java多消费者问题对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、java多生产者和多消费者
- 2、java多生产者和消费者问题,重复生产消费
- 3、JAVA多生产者多消费者问题。希望用wait()和notify().谢谢!
- 4、java多生产者-多消费者问题(+高分哦!)
java多生产者和多消费者
public static void main(String[] args) {
Buffer buffer=new Buffer(); //创建一个临界区对象
new Producer(buffer,100).start(); //创建一个生产者对象,并启动其线程
new Consumer(buffer,200).start(); //创建一个消费者对象,并启动其线程
new Consumer(buffer,201).start(); //创建第二个消费者对象,并启动其线程
}
这一段代码,多加入
new Consumer(buffer,201).start(); //创建第二个消费者对象,并启动其线程
多加一段代码创建一个消费者
多加入
new Producer(buffer,100).start();
创建一个生产者。
想要很多生产者和消费者?加就是了啊。
第四个文件 Buffer.java
这个是实现同步的主要缓存类。想要实现同步
在每个方法的声明前都加入synchronized 就行
synchronized 线程锁,很好用的。源代码已经加入了
就比如
public synchronized void put(int value) { //同步方法控制临界区内容写入
java多生产者和消费者问题,重复生产消费
我晕看了好久,别人写的代码看的真是辛苦,也没注释...修改了一堆括号!!
妥妥的没问题,你的资源用的数组,换句话说,
你数组被A1线程增加索引1,然后B过来拿走索引1; 数组里面此刻是什么?当然是0了啊;因为你递减了...
然后A2被拿到执行权,怎么样?是不是还去增加索引1??明白了?
如果你想要不重复,就别递减就行了!
另外你这么改,有什么问题看的很醒目,知道发生在哪个线程上!
JAVA多生产者多消费者问题。希望用wait()和notify().谢谢!
public class ProduceConsumerDemo {
public static void main(String[] args) {
// 1.创建资源
Resource resource = new Resource();
// 2.创建两个任务
Producer producer = new Producer(resource);
Consumer consumer = new Consumer(resource);
// 3.创建线程
/*
* 多生产多消费产生的问题:重复生产、重复消费
*/
Thread thread0 = new Thread(producer);
Thread thread1 = new Thread(producer);
thread0.setName("生产者(NO0)");
thread1.setName("生产者(NO1)");
Thread thread2 = new Thread(consumer);
Thread thread3 = new Thread(consumer);
thread2.setName("消费者(NO2)");
thread3.setName("消费者(NO3)");
thread0.start();
thread1.start();
thread2.start();
thread3.start();
}
}
class Resource {
private String name;
private int count = 1;
// 定义标记
private boolean flag;
// 提供给商品赋值的方法
public synchronized void setName(String name) {// thread0, thread1在这里运行
while (flag)// 判断标记为true,执行wait等待,为false则生产
/*
* 这里使用while,而不使用if的理由如下:
*
* thread0有可能第二次也抢到锁的执行权,判断为真,则有面包不生产,所以接下来执行等待,此时thread0在线程池中。
* 接下来活的线程有3个(除了thread0),这三个线程都有可能获取到执行权.
* 假设thread1获得了执行权,判断为真,则有面包不生产,执行等待。此时thread1又进入到了线程池中。
* 接下来有两个活的线程thread2和thread3。 假设thread2又抢到了执行权,所以程序转到了消费get处……
*/
try {
this.wait();//这里wait语句必须包含在try/catch块中,抛出异常。
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name + count;// 第一个面包
count++;// 2
System.out.println(Thread.currentThread().getName() + this.name);// thread0线程生产了面包1
// 生产完毕,将标记改成true.
flag = true;// thread0第一次生产完面包以后,将标记改为真,表示有面包了
// 唤醒消费者(这里使用notifyAll而不使用notify的原因在下面)
this.notifyAll();// 第一次在这里是空唤醒,没有意义
}
/*
* 通过同步,解决了没生产就消费的问题
* 生产完以后,生产者释放了this锁,此时,生产者和消费者同时去抢锁,又是生产者抢到了锁,所以就出现了一直生产的情况。
* 与“生产一个就消费一个的需求不符合” 等待唤醒机制 wait();该方法可以使线程处于冻结状态,并将线程临时存储到线程池
* notify();唤醒指定线程池中的任意一个线程。 notifyAll();唤醒指定线程池中的所有线程
* 这些方法必须使用在同步函数中,因为他们用来操作同步锁上的线程上的状态的。
* 在使用这些方法时候,必须标识他们所属于的锁,标识方式就是锁对象.wait(); 锁对象.notify(); 锁对象.notifyAll();
* 相同锁的notify()可以获取相同锁的wait();
*/
public synchronized void getName() {// thread2,thread3在这里运行
while (!flag)
/*
* ……接着上面的程序执行分析 thread2拿到锁获取执行权之后,判断!flag为假,则不等待,直接消费面包1,输出一次.
* 消费完成之后将flag改为假 接下来又唤醒了thread0或者thread1生产者中的一个
* 假设又唤醒了thread0线程,现在活的线程有thread0,thread2,thread3三个线程
* 假设接下来thread2又抢到了执行权,判断!flag为真,没面包了,停止消费,所以thread2执行等待.
* 此时活着的线程有thread0和thread3。
* 假设thread3得到了执行权,拿到锁之后进来执行等待,此时活着的线程只有thread0.
* 所以thread0只能抢到执行权之后,生产面包2,将标记改为true告诉消费者有面包可以消费了。
* 接下来执行notify唤醒,此时唤醒休眠中的3个线程中的任何一个都有可能。
* 如果唤醒了消费者thread2或者thread3中的任何一个,程序都是正常。如果此时唤醒thread1则不正常。
* 如果唤醒了thread1,此时活着的线程有thread0和thread1两个线程。
* 假设thread0又获得了执行权,判读为真有面包,则又一次执行等待。
* 接下来只有thread1线程有执行权(此时没有判断标记直接生产了,出错了),所以又生产了面包3。 在这个过程中,面包2没有被消费。
* 这就是连续生产和消费容易出现的问题。
*
* 原因:被唤醒的线程没有判断标记就开始执行了,导致了重复的生产和消费发生。
*
* 解决:被唤醒的线程必须判断标记,使用while循环标记,而不使用if判断的理由。
*
* 但是接下来会出现死锁,原因在于:
* 上面的程序中thread0在执行notify的时候唤醒了thread1,而此时thread2和thread3两个消费者线程都处于等待状态
* thread1在执行while判断语句之后判断为真,则执行等待,此时所有的线程都处于冻结等待状态了。
*
* 原因:本方线程在执行唤醒的时候又一次唤醒了本方线程,而本方线程循环判断标记又继续等待,而导致所有的线程都等待。
*
* 解决:本方线程唤醒对方线程, 可以使用notifyAll()方法
* 唤醒之后,既有本方,又有对方,但是本方线程判断标记之后,会继续等待,这样就有对方线程在执行。
*/
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + this.name);
// 将标记改为false
flag = false;
// 唤醒生产者
this.notify();
}
}
// 生产者
class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
public void run() {
while (true) {
resource.setName("面包");
}
}
}
// 消费者
class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
resource.getName();
}
}
}
java多生产者-多消费者问题(+高分哦!)
生产者向阻塞队列中放入随即整数(可以为两个消费者提供不同的队列),消费者从队列中取出元素进行判断,可以用BlockingQueue实现同步,很方便,质数和平方数判断在写个静态方法即可~自己想想看,需要代码就说下
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class Producer extends Thread
{
private ListBlockingQueueInteger queueList;
public Producer(ListBlockingQueueInteger bQueueList)
{
this.queueList = bQueueList;
}
public void run()
{
int count = 0;
while (count++ 10)
{
int randomInt = (int) (Math.random() * 100 + 1);
try
{
for(BlockingQueueInteger queue:queueList)
{
queue.put(randomInt);
}
System.out.println(randomInt + " is put..");
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args)
{
BlockingQueueInteger bQueue = new LinkedBlockingQueueInteger();
BlockingQueueInteger bQueueCopy = new LinkedBlockingQueueInteger();
ListBlockingQueueInteger list=new ArrayListBlockingQueueInteger();
list.add(bQueue);
list.add(bQueueCopy);
new Producer(list).start();
new Producer(list).start();
new Producer(list).start();
new PrimeConsumer(bQueue).start();
new SquareConsumer(bQueueCopy).start();
}
}
class PrimeConsumer extends Thread
{
private BlockingQueue queue;
public PrimeConsumer(BlockingQueueInteger bQueue)
{
this.queue = bQueue;
}
public void run()
{
do
{
try
{
int i = (Integer) queue.take();
if (CheckNumber.isPrime(i))
{
System.out.println(i + " is prime..");
}
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
while (queue.size() != 0);
}
}
class SquareConsumer extends Thread
{
private BlockingQueue queue;
public SquareConsumer(BlockingQueueInteger bQueue)
{
this.queue = bQueue;
}
public void run()
{
do
{
try
{
int i = (Integer) queue.take();
if (CheckNumber.isSquare(i))
{
System.out.println(i + " is square..");
}
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
}
while (queue.size() != 0);
}
}
class CheckNumber
{
public static boolean isPrime(int n)
{
if (n == 1)
return false;
for (int i = 2; i n / 2 + 1; i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
public static boolean isSquare(int n)
{
int l = (int) Math.sqrt(n);
for (int i = 1; i = l; i++)
{
if (i * i == n)
{
return true;
}
}
return false;
}
}
都写在一个类里了,比较乱,测试正确~
关于java多消费和java多消费者问题的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
发布于:2022-11-25,除非注明,否则均为
原创文章,转载请注明出处。