Java 就 生产者——消费者 理解 等待池、锁池,以及synchronized的简单用法

引入

在学习过程中,我们可能听过关于”线程安全“的问题,就StringBufferStringBuilder而言,StringBuffer是线程安全的,而StringBuilder不是,,

敢问为何如此“,,

大多数回答都是:

StringBuffer里对应的方法有synchronized 修饰,而StringBuilder里没有。“

然后就没了。

So,,此时我们只能靠自己了。What is the synchronized?

synchronized 是Java中的 关键字,是一种同步锁,被其修饰过的代码块方法静态方法 中的 对象 ,在某一时刻只能被一个线程访问。

生产者——消费者

在这之前先说明两个概念, 等待池 and 锁池

锁池:现存在一个对象(O对象),有一个线程(a线程)正在执行 O对象 中被 synchronized 修饰的同步方法,,那么,此时的 a线程 正持有着 此对象的 锁,其他线程在 请求该 锁 的时候就会被阻塞,然后进入该对象的 锁池 中。

等待池:如果一个线程(线程A)调用了某个对象的 wait()方法,那么线程A就会释放 该对象的所有锁,然后进入该对象的 等待池。

首先设置 缓冲区

缓冲区的作用:为了缓解 生产 和 消费 速度不匹配 的问题。

  • 这里用一个 栈 SynStack (后进先出)来做缓冲区
/**
 * @ClassName SynStack
 * @Description buffer——缓冲区 的大小 为 3
 * @Author SkySong
 * @Date 2020-04-06 19:26
 */
public class SynStack {
    private int index = 0;
    private char[] buffer = new char[3];
    public synchronized void push(char c){
        while (index == buffer.length){
            try {
                System.out.println("生产阻塞,下一条Produced被阻塞");
                this.wait();//生产线程进入等待池
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notify();//从等待池 中 唤醒被阻塞的那一条线程(消费进程)
        //被唤醒的消费线程会开始消费
        buffer[index] = c;
        index++;
    }

    public synchronized char pop(){
        while (index == 0){
            try {
                System.out.println("消费阻塞");
                this.wait();//消费线程进入等待池
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notify();//从等待池 中 唤醒被阻塞的那一条线程(生产进程)
        //被唤醒的生产线程会继续完成 当条 生产
        index--;
        return buffer[index];
    }
}
  • 生产者 Producer
/**
 * @ClassName Producer
 * @Description
 * @Author SkySong
 * @Date 2020-04-06 19:41
 */
public class Producer implements Runnable{

    SynStack stack;

    public Producer(SynStack stack) {
        this.stack = stack;
    }

    @Override
    public void run() {
        char c;
        for (int i = 0;i < 10;i++){
            c = (char) (Math.random()*26+'A');
            stack.push(c);
            System.out.println("Produced: "+c);
            try {
            	//让生产者睡的短一点
                Thread.sleep((long) (Math.random()*100));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 消费者 Consumer
/**
 * @ClassName Consumer
 * @Description
 * @Author SkySong
 * @Date 2020-04-06 20:54
 */
public class Consumer implements Runnable{
    SynStack stack;

    public Consumer(SynStack stack) {
        this.stack = stack;
    }

    @Override
    public void run() {
        char c;
        for (int i = 0;i < 10;i++){
            c = stack.pop();
            System.out.println("Consumer: "+c);
            try {
            	//多睡会,让生产者先生产
                Thread.sleep((long) (Math.random()*1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 测试 Test
	SynStack synStack = new SynStack();//缓存区
	Runnable add = new Producer(synStack);
	Runnable minus = new Consumer(synStack);
	new Thread(add).start();
	new Thread(minus).start();
  • 运行结果 Result

消费阻塞                                     开始缓冲区里没有产品,消费线程执行wait()方法,进入等待池中
Produced: K                               生产出了一个K,同时唤醒消费线程(从等待池中拽到锁池中)
Consumer: K                             消费了一个K
Produced: V
Produced: P
Produced: N                              最外层的产品
生产阻塞,下一条被阻塞           前面已经生产了3个了,缓冲区满了
Produced: R                              此时该线程应当执行wait()方法,进入等待池
Consumer: N                   消费了栈(缓冲区)中最外面的一个产品N,同时执行了notify()方法,将生产线程唤醒
生产阻塞,下一条被阻塞
Produced: K
Consumer: R                这里为什么是R,因为被唤醒的生产线程会继续生产完当初被阻塞的产品
生产阻塞,下一条被阻塞
Produced: L
Consumer: K
生产阻塞,下一条被阻塞
Consumer: L
Produced: J
生产阻塞,下一条被阻塞
Produced: B
Consumer: J
生产阻塞,下一条被阻塞
Consumer: B
Produced: Q
Consumer: Q
Consumer: P
Consumer: V

最后补充一下notify()的作用:

notify():随机在等待池中 唤醒(这个词可能不准确)一个线程,将线程 从 等待池———>锁池,又有了和其他线程争夺 对象锁 的权利了

notifyAll(): 将等待池里的所有线程 都叫 ”醒“。

That’s all ,. Thank you !

原创文章 10 获赞 10 访问量 441

猜你喜欢

转载自blog.csdn.net/weixin_43415201/article/details/105353119
今日推荐