Java---并发和同步(生产者--消费者)

本文深入探讨Java中的进程与线程的区别、并发性及线程同步机制,通过具体示例解析synchronized关键字的使用方法及其特性。并介绍了生产者消费者模式在解决多线程间数据共享问题的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并发:这里先说下进程和线程的区别 :
一个程序至少需要一个进程一个线程,进程是独立于内存 ,线程是共享于内存 ,并发性高 也就是说 线程只能是在应用中存在。
并发性在程序里指多个线程同时访问,然java是通过时间片化,实现多线程的 也就是并发 。
同步
线程同步 是指一个线程对象同一时间在同一个方法里执行一次
买票问题 :首先票是唯一的 而买票窗口是N个 如果不同步,那么很有可能一张票卖给两个人,解决这个问题 就是在销售票时 后面的线程进入阻塞状态,等前面的线程结束 释放之后 再进行买票 ` class Threadss implements Runnable {

private  int a=6666;
public void run(){
    for (int i = 0; i <100000; i++) {
        if(a>0){
            System.out.println("售票编号 "+a--);
        }
    }
}

}`

public static void main(String[] args) {
        Threadss a=new Threadss();
        Threadss b=new Threadss();
        Threadss c=new Threadss();
        a.run();
        b.run();
        /*b.run();
        c.run();*/

那么什么是阻塞呢?这里我们要必须知道一个问题 那就是对象监视器 monitor 很多地方称为锁 java规定每个对象都有一个锁 ,而且这个锁只有在同步块里才能被正确使用
synchronized 里面 :锁 只能有被一个线程占用,后面不管有多个,都只能等待,只有该线程使用完 才能释放 ,也有这样一种情况 。例如有一个同步方法 method(); 里面有两个实例 a b 同一时刻a.method() 和b,method() 不冲突 都能完美的调用
所以买票的逻辑在同步块里实现 那么就不会出现一张票两个人的问题
synchronized特点:
1、放方法名前是同步方法 放在块前是同步块
2、当作为块时不能放在if 后面。
锁和同步时注意的
(1)只能同步方法 不能同步变量和类
(2)同步方法所在的类 可以有非同步的方法 程序需要同步时就加synchronized
(3)如果一个线程拥有同步和非同步方法,则非同步方法可以被多个线程自由访问而不受锁限制
(4)线程可以获得多个锁,一个对象的同步方法里面调用另一个对象的同步方法,则获得两个对象的监视器
(5)同步损坏并发性, 同步不仅同步某个方法,还可以同步方法里的末以块
(6)同步静态的方法,则需要把整个类都加上锁 synchronized
wait notify() notifyAll()的使用

wait()
使本线程挂起 挂起的对象将释放montor ,只有其他线程使用notify 和 notifyAll 才能被唤醒使用
notify()
是随机唤醒一个线程
notifyAll()
唤醒所有该对象的沉睡线程,唤起的线程会继续争夺monitor的占有权 最终会有一个占有 其他线程继续等待
下面讨论一个典型问题 生产者和消费者模式
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式
什么是生产者消费者模式
这里要引用阻塞队列 ,当生产者生成数据时放入阻塞队列里,消费者从阻塞队列里拿数据,而不找生产者拿数据从阻塞缓冲区里拿数据
生成者和消费者是解决二者之间阻抗效率问题,耦合只是附带的
实例
一个馒头店,厨师生产馒头,放到篮子里,客人从里面拿然后吃掉,当篮子满时 厨师让客人来吃,当篮子空时 让厨师生产

  1. 生产的物品馒头
package org.com.action;
/**
 * 生产的数据  例如馒头
 * @author wangfeng
 *
 */
public class Mantou {
   private int index;
   //有参构造方法
 public Mantou(int index){
     this.index=index;
  }
 //重写toString 输出
 public String toString(){
    return "Mantou--"+index;

 }

2、篮子

package org.com.action;

public class Basket {
    private int i=0; //表示装第几个馒头
    private  Mantou[] mantou=new Mantou[6];  //篮子的数量
    //生成者
    public synchronized void pro(Mantou m){
        //这里当篮子满时提示客人来吃
        while(i==mantou.length){

              try {
                  System.out.println("篮子满了");

                this.wait(); //线程暂停,等待唤醒
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
         System.out.println(Thread.currentThread().getName()+"生成"+m.toString());
         this.notify(); //生产完,唤醒线程
         mantou[i]=m;  //把馒头塞进篮子里
         i++;
    }
    //消费者
    public synchronized Mantou con(){
         while(i==0){
             try {
                 System.out.println("篮子空");
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

         }
         Mantou is=mantou[--i];
         System.out.println(Thread.currentThread().getName()+"消费"+is.toString());
         this.notify();
         return is;
    }
}


3 厨师

package org.com.action;
/**
 * 生产者
 * @author wangfeng
 *
 */

public class Produce implements Runnable {
  private  Basket b;
  public Produce(Basket b){
      this.b=b;
  }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i <20; i++) {
            Mantou m=new Mantou(i);
            b.pro(m);
            try {
                Thread.sleep(500);//阻塞线程
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

4 消费者

package org.com.action;

public class Consumer implements Runnable {
  private Basket b;
  public Consumer(Basket b){
      this.b=b;
  }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 20; i++) {
            Mantou m=b.con();
             try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }

}

5 mian

package org.com.action;

public class ThreeClass {
        public static void main(String[] args) {
         Basket b=new Basket();
          new Thread(new Produce(b)).start();
          new Thread(new Consumer(b)).start();

        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值