3.5生产者与消费者

多生产者与多消费者-操作值:假死

假死 是所有线程都进入了waiting状态

下面是一个假死的例子

package com.myObject;

public class ProducerObject {
    private String lock;

    public ProducerObject(String lock) {
        this.lock = lock;
    }

    public void p() {
        synchronized (lock) {
            try {
                while (!"".equals(ValueObject.value)) {
                    System.out.println("P wait begin "+ System.currentTimeMillis());
                    lock.wait();
                }
                System.out.println("P wait end " + System.currentTimeMillis());
                String value = System.currentTimeMillis() + "_"+ System.nanoTime();
                ValueObject.value = value;
                lock.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
package com.myObject;

public class CustomerObject {
    private String lock;

    public CustomerObject(String lock) {
        this.lock = lock;
    }

    public void c() {
        synchronized (lock) {
            try {
                while ("".equals(ValueObject.value)) {
                    System.out.println("C wait begin "+ System.currentTimeMillis());
                    lock.wait();
                }
                System.out.println("C wait end " + System.currentTimeMillis());
                String value = "";
                ValueObject.value = value;
                lock.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
package com.myObject;

public class ValueObject {

    public static String value = "";

}
package com.myThread;

import com.myObject.ProducerObject;

public class Thread1a extends Thread {
    ProducerObject producerObject;

    public Thread1a(ProducerObject producerObject) {
        this.producerObject = producerObject;
    }

    @Override
    public void run() {
        while(true){
            producerObject.p();
        }
    }
}
package com.myThread;

import com.myObject.CustomerObject;

public class Thread1b extends Thread {
    CustomerObject customerObject;

    public Thread1b(CustomerObject customerObject) {
        this.customerObject = customerObject;
    }

    @Override
    public void run() {
        while(true){
            customerObject.c(); 
        }
    }
}
package com.test;

import com.myObject.CustomerObject;
import com.myObject.ProducerObject;
import com.myThread.Thread1a;
import com.myThread.Thread1b;

public class Test1 {
    public static void main(String[] args) throws InterruptedException{
        String lock = new String("");
        ProducerObject p= new ProducerObject(lock);//生产者
        CustomerObject c = new CustomerObject(lock);//消费者
        Thread1a[] arrThread1a = new Thread1a[3];
        Thread1b[] arrThread1b = new Thread1b[3];
        for(int i = 0;i < 3;i++){
            arrThread1a[i] = new Thread1a(p);
            arrThread1a[i].setName("p"+(i+1));
            arrThread1b[i] = new Thread1b(c);
            arrThread1b[i].setName("c"+(i+1));
            arrThread1a[i].start();
            arrThread1b[i].start();

        }
        Thread.sleep(5000);
        Thread[] threads = new Thread[Thread.currentThread().getThreadGroup().activeCount()];
        Thread.currentThread().getThreadGroup().enumerate(threads);
        for(int  i= 0;i< threads.length;i++ ){
            System.out.println(threads[i].getName()+" "+threads[i].getState());
        }



    }
}

打印结果

C wait begin 1453112093337
C wait begin 1453112093338
C wait begin 1453112093338
P wait end 1453112093338
P wait begin 1453112093338
P wait begin 1453112093338
P wait begin 1453112093338
main RUNNABLE
p1 WAITING
c1 WAITING
p2 WAITING
c2 WAITING
p3 WAITING
c3 WAITING

结果分析:问题出在lock.notify()。比如p唤醒p,c唤醒c都会进入waiting,这样运行久了,会导致所有线程都进入waiting,程序最后进入假死,不能继续运行

解决方法是将notify改为notifyAll,这样无论通知“同类”还是“异类”,保证至少有一个线程还在运行

多生产者与多消费者-操作栈:解决wait条件改变与假死

多个生产者向List中放入数据,多个消费者从List中取出数据,List最大容量为1即控制List.size最大为1。

1)解决wait条件改变需将if改为while

wait条件改变错误结果


pop end 0
pop=anyStr0.04638034362500809
push end 1
Exception in thread "c3" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at com.myObject.StackObject.pop(StackObject.java:30)
at com.myObject.CustomerObject2.pop(CustomerObject2.java:11)
at com.myThread.Thread2b.run(Thread2b.java:15)
pop end 0
pop=anyStr0.98486043968257
pop begin and c2is waiting

2)解决wait条件改变之后还需要解决假死,则需将notify改为notifyAll

假死错误结果

pop=anyStr0.08915212675142581
push end 1
pop end 0
pop=anyStr0.24479882846755296
pop begin and c2is waiting
pop begin and c4is waiting
pop begin and c3is waiting
push end 1



先来看正确例子

package com.myObject;

public class CustomerObject2 {
    private StackObject stackObject;

    public CustomerObject2(StackObject stackObject) {
        this.stackObject = stackObject;
    }

    public void pop(){
        System.out.println("pop="+stackObject.pop());
    }
}
package com.myObject;

public class ProducerObject2 {
    private StackObject stackObject;

    public ProducerObject2(StackObject stackObject) {
        this.stackObject = stackObject;
    }

    public void push(){
        stackObject.push();
    }
}
package com.myThread;

import com.myObject.ProducerObject2;

public class Thread2a extends Thread {
    ProducerObject2 producerObject2;

    public Thread2a(ProducerObject2 producerObject2) {
        this.producerObject2 = producerObject2;
    }

    @Override
    public void run() {
        while(true){
            producerObject2.push();
        }
    }
}
package com.myThread;

import com.myObject.CustomerObject2;

public class Thread2b extends Thread {
    CustomerObject2 customerObject2;

    public Thread2b(CustomerObject2 customerObject2) {
        this.customerObject2 = customerObject2;
    }

    @Override
    public void run() {
        while(true){
            customerObject2.pop();  
        }
    }
}
package com.test;

import com.myObject.CustomerObject2;
import com.myObject.ProducerObject2;
import com.myObject.StackObject;
import com.myThread.Thread2a;
import com.myThread.Thread2b;

public class Test2 {
    public static void main(String[] args) throws InterruptedException{
        StackObject stackObject = new StackObject();
        ProducerObject2 p= new ProducerObject2(stackObject);
        CustomerObject2 c = new CustomerObject2(stackObject);
        Thread2a[] arrThread2a = new Thread2a[3];
        Thread2b[] arrThread2b = new Thread2b[3];
        for(int i = 0;i < 3;i++){
            arrThread2a[i] = new Thread2a(p);
            arrThread2a[i].setName("p"+(i+2));
            arrThread2b[i] = new Thread2b(c);
            arrThread2b[i].setName("c"+(i+2));
            arrThread2a[i].start();
            arrThread2b[i].start();

        }


    }
}
package com.myObject;

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

public class StackObject {
    private List list = new ArrayList();
    //生产者压栈
    synchronized public void push() {
        try {
            while(list.size()==1){
                this.wait();
            }
            list.add("anyStr"+Math.random());
            this.notifyAll();
            System.out.println("push end "+list.size());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //消费者出栈
    synchronized public String pop() {
        String pop="";
        try {
            while(list.size()==0){
                System.out.println("pop begin and "+Thread.currentThread().getName()+"is waiting");
                this.wait();
            }
            pop=""+list.get(0);
            list.remove(0);
            this.notifyAll();
            System.out.println("pop end "+list.size());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return pop;
    }

}

下面是关键代码错误的地方 if 和 notify

package com.myObject;

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

public class StackObject {
    private List list = new ArrayList();
    //生产者压栈
    synchronized public void push() {
        try {
            if(list.size()==1){
                this.wait();
            }
            list.add("anyStr"+Math.random());
            this.notify();
            System.out.println("push end "+list.size());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //消费者出栈
    synchronized public String pop() {
        String pop="";
        try {
            if(list.size()==0){
                System.out.println("pop begin and "+Thread.currentThread().getName()+"is waiting");
                this.wait();
            }
            pop=""+list.get(0);
            list.remove(0);
            this.notify();
            System.out.println("pop end "+list.size());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return pop;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Kafka 3.5的部署,你可以按照以下步骤进行操作: 1. 安装Java:首先,确保在部署Kafka之前已经安装了Java。Kafka需要Java环境来运行。你可以从Oracle官方网站上下载并安装适合你系统的Java版本。 2. 下载Kafka:从Apache Kafka的官方网站(http://kafka.apache.org/downloads)上下载适合你系统的Kafka版本。选择一个稳定版本并下载压缩包。 3. 解压缩Kafka:将下载的Kafka压缩包解压到你想要安装的目录下。 4. 配置Kafka:进入解压后的Kafka目录,在config文件夹中找到server.properties文件,打开并根据自己的需求进行配置。你可以修改Zookeeper连接信息、Kafka监听端口等参数。 5. 启动Zookeeper:在Kafka的解压目录中找到bin文件夹,启动一个Zookeeper实例。运行以下命令: ``` ./zookeeper-server-start.sh ../config/zookeeper.properties ``` 6. 启动Kafka Broker:在同样的bin文件夹下启动Kafka Broker实例。运行以下命令: ``` ./kafka-server-start.sh ../config/server.properties ``` 7. 创建Topic:使用Kafka提供的命令行工具创建一个Topic。运行以下命令: ``` ./kafka-topics.sh --create --topic YOUR_TOPIC_NAME --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1 ``` 将YOUR_TOPIC_NAME替换为你想要创建的Topic名称。 8. 发布和消费消息:使用Kafka提供的命令行工具来发布和消费消息。可以使用以下命令分别启动一个生产者和一个消费者: ``` ./kafka-console-producer.sh --topic YOUR_TOPIC_NAME --bootstrap-server localhost:9092 ``` ``` ./kafka-console-consumer.sh --topic YOUR_TOPIC_NAME --bootstrap-server localhost:9092 ``` 将YOUR_TOPIC_NAME替换为你创建的Topic名称。 这样,你就完成了Kafka 3.5的部署。你可以根据自己的需求进一步配置和使用Kafka。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值