线程同步--生产者和消费者例子

前言

  小编最近在学习线程的内容,发现里面的小例子实现起来非常的有意思,当然也非常有用,线程的内容,几乎是我们每天都会遇到,但是不是特别注意的,下面小编带大家进一步认识线程吧!

线程和进程

1.线程是一个程序内部的顺序控制流
2.线程和进程区别:
(1)每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销;
(2)线程可以看成轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小;
(3)多进程:在操作系统中能同时运行多个任务(程序);
(4)多线程:在同一个应用程序中有多个顺序流同时执行。

线程同步

  在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。
  1.对象互斥锁
  每个对象都对应于一个可称为“互斥锁”的标记,这个标记保证在任何一时刻,只能有一个线程访问该对象。
  2.关键字synchronized
  synchronized来与对象的互斥锁联系,当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。

生产者和消费者的例子


1.代码分析
(1)共有5个类:主程序类ProducerConsumer、生产的食物类WoTou、实现线程同步的加锁类SyncStack、生产者类Producer和消费者类Consumer
(2)Producer和Consumer实现了接口Runnable,属于两个线程;
(3)当在执行线程同步时,如果生产的数量超出了容器即数组的索引值6的话,则执行Object.wait()的方法,否则激活另一个线程消费Consumer,使用Object .notify()方法。
2.代码实现

public class ProducerConsumer {


    public static void main(String[] args) throws Exception{
        SyncStack ss=new SyncStack();
        Producer p=new Producer(ss);
        Consumer c=new Consumer(ss);

        new Thread(p).start();
        new Thread(c).start();


    }

}

class WoTou{
    int id;
    WoTou(int id){
        this.id=id;
    }

    public String toString(){
        return "wotou: "+id;
    }
}

class SyncStack{
    int index=0;
    WoTou[] arrWT=new WoTou[6];

    public synchronized void push(WoTou wt){
        while(index==arrWT.length){
            try{
               this.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        this.notify();
        arrWT[index]=wt;
        index++;
    }

    public synchronized WoTou pop(){
        while(index==0){
            try{
                this.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
        this.notify();
        index--;
        return arrWT[index];

    }

}

class Producer implements Runnable{
    SyncStack ss=new SyncStack();
    Producer(SyncStack ss){
        this.ss=ss;
    }

    public void run(){
        for(int i=0;i<=20;i++){
            WoTou wt=new WoTou(i);
            ss.push(wt);
            System.out.println("生产了  "+wt);
            try{
              Thread.sleep((int)(Math.random()*1000));
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable{
    SyncStack ss=new SyncStack();
    Consumer(SyncStack ss){
        this.ss=ss;
    }

    public void run(){
        for(int i=0;i<=20;i++){
            WoTou wt=ss.pop();
            System.out.println("消费了  "+wt);
            try{
              Thread.sleep((int)(Math.random()*1000));
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}

小结

  线程同步,是在面试中经常可以会被问到的题目,这个小例子如果自己能够动手写出来,充分理解之后,相信会很有帮助。

感谢您的访问!

猜你喜欢

转载自blog.csdn.net/m18633778874/article/details/80192390