首页 > 其他分享 >线程同步(synchronized)(重点)

线程同步(synchronized)(重点)

时间:2022-12-08 16:03:12浏览次数:58  
标签:Product 同步 container synchronized class 线程 new public SynContainer

线程同步(synchronized)(重点)

  • 同步方法(同步方法,锁的是this类本身)

    image-20221208094206244

  • 同步块(synchronized(Obj){})

    • Obj称为同步监视器
    • image-20221208094631346

死锁

image-20221208110852733

lock(锁)ReentrantLock类(可重入锁)实现Lock,可以显示加锁、释放锁。

image-20221208111903195

img

package com.fjbc.多线程;

import java.util.concurrent.locks.ReentrantLock;

//测试Lock锁
public class Demo32_ThreadLock {
    public static void main(String[] args) {
        TestLock testLock = new TestLock();
        new Thread(testLock).start();
        new Thread(testLock).start();
        new Thread(testLock).start();

    }
}

class TestLock implements Runnable {
    int tickerNums = 10;
    //定义Lock锁
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            //加锁
            try {
                lock.lock();
                if (tickerNums <= 0) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(tickerNums--);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //解锁
                lock.unlock();
            }
        }
    }
}

(难)线程协作通信(生产者消费者模式)

  • 管程法

    • package com.fjbc.多线程;
      
      /**
       * 测试:生产者消费者模型-->利用缓冲区解决:管程法
       */
      public class Demo33_ThreadPC {
          public static void main(String[] args) {
              SynContainer synContainer = new SynContainer();
              new Producer(synContainer).start();
              new Consumer(synContainer).start();
          }
      }
      
      //生产者
      class Producer extends Thread {
          //容缓冲区
          SynContainer container;
      
          public Producer(SynContainer container) {
              this.container = container;
          }
      
          //生产
          @Override
          public void run() {
              for (int i = 0; i < 100; i++) {
                  container.push(new Product(i));
                  System.out.println("生产了" + i + "件产品");
              }
          }
      }
      
      //消费者
      class Consumer extends Thread {
          //容缓冲区
          SynContainer container;
      
          public Consumer(SynContainer container) {
              this.container = container;
          }
      
          //消费
          @Override
          public void run() {
              for (int i = 0; i < 100; i++) {
                  System.out.println("消费了-->" + container.pop().id + "件产品");
              }
          }
      }
      
      //产品
      class Product {
          int id;//产品编号
      
          public Product(int id) {
              this.id = id;
          }
      }
      
      //缓冲区
      class SynContainer {
          //需要一个容器大小
          Product[] products = new Product[10];
          //容器计数器
          int count = 0;
      
          //生产者放入产品
          public synchronized void push(Product product) {
              //如果容器满了,需要等待消费者消费
              /*如果是if的话,假如消费者1消费了最后一个,这是index变成0此时释放锁被消费者2拿到而不是生产者拿到,这时消费者的wait是在if里所以它就直接去消费index-1下标越界,如果是while就会再去判断一下index得值是不是变成0了*/
              while (count == products.length) {
                  //通知消费者消费,等待生产
                  try {
                      this.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              //如果没有满,需要丢入产品
              products[count] = product;
              count++;
              //通知消费者消费
              this.notifyAll();
          }
      
          //消费者消费产品
          public synchronized Product pop() {
              //判断是否能消费
              while (count <= 0) {
                  //等待生产者生产
                  try {
                      this.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              //如果可以消费
              count--;
              Product product = products[count];
              //吃完了 通知生产者生产
              this.notifyAll();
              return product;
          }
      }
      
  • 信号灯法

    • package com.fjbc.多线程;
      
      public class Demo34_ThreadPool {
          /**
           * 测试:生产者消费者模型-->利用缓冲区解决:管程法
           */
              public static void main(String[] args) {
                  SynContainer synContainer = new SynContainer();
                  new Producer(synContainer).start();
                  new Consumer(synContainer).start();
              }
          }
      
          //生产者
          class Producer1 extends Thread {
              //容缓冲区
              SynContainer container;
      
              public Producer1(SynContainer container) {
                  this.container = container;
              }
      
              //生产
              @Override
              public void run() {
                  for (int i = 0; i < 100; i++) {
                      container.push(new Product(i));
                      System.out.println("生产了" + i + "件产品");
                  }
              }
          }
      
          //消费者
          class Consumer1 extends Thread {
              //容缓冲区
              SynContainer container;
      
              public Consumer1(SynContainer container) {
                  this.container = container;
              }
      
              //消费
              @Override
              public void run() {
                  for (int i = 0; i < 100; i++) {
                      System.out.println("消费了-->" + container.pop().id + "件产品");
                  }
              }
          }
      
          //产品
          class Product1 {
              int id;//产品编号
      
              public Product1(int id) {
                  this.id = id;
              }
          }
      
          //缓冲区
          class SynContainer1 {
              //需要一个容器大小
              Product[] products = new Product[10];
              //容器计数器
              int count = 0;
      
              //生产者放入产品
              public synchronized void push(Product product) {
                  //如果容器满了,需要等待消费者消费
                  /*如果是if的话,假如消费者1消费了最后一个,这是index变成0此时释放锁被消费者2拿到而不是生产者拿到,这时消费者的wait是在if里所以它就直接去消费index-1下标越界,如果是while就会再去判断一下index得值是不是变成0了*/
                  while (count == products.length) {
                      //通知消费者消费,等待生产
                      try {
                          this.wait();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                  //如果没有满,需要丢入产品
                  products[count] = product;
                  count++;
                  //通知消费者消费
                  this.notifyAll();
              }
      
              //消费者消费产品
              public synchronized Product pop() {
                  //判断是否能消费
                  while (count <= 0) {
                      //等待生产者生产
                      try {
                          this.wait();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                  //如果可以消费
                  count--;
                  Product product = products[count];
                  //吃完了 通知生产者生产
                  this.notifyAll();
                  return product;
              }
          }
      
      
      
      

使用线程池

img

img

    1. 创建服务,创建线程池(newFixedThreadPool(线程池大小)):ExecutorService service = Executors.newFixedThreadPool(10);
    2. 执行(service.execute(new MyThread());)
    3. 关闭连接(service.shutdown();)

标签:Product,同步,container,synchronized,class,线程,new,public,SynContainer
From: https://www.cnblogs.com/fjbc/p/16966333.html

相关文章

  • 随笔(四)『Java多线程(创建线程方式)』
    1、创建线程方式一:『继承Thread类』/***创建线程方式一:『继承Thread类』*/publicclassThreadTest{publicstaticclassMyThreadextendsThread{......
  • 多线程的原子性,可见性,有序性
    java内存模型定义了主存,工作内存等这些抽象概念,底层对应着cpu寄存器,缓存,cpu指令优化等。由此引出了原子性,可见性,有序性一、原子性保证指令不会受到上下文切换的影响而......
  • 同步导航菜单与路由,并在关闭标签(或浏览器)后重新时,维持离开时的路由
    简介PC端路由跳转除了各种点击事件外,还经常会通过前进后退键触发,此时,为了确保导航菜单与路由地址的同步关系,就需要在菜单点击事件的基础上,新增对路由的侦听。同时,若是希......
  • 线程池工作流程
     CorePoolSize:核心线程数。MaximumPoolSize:最大线程数。WorkQueue:工作队列。 流程创建线程池后,等待提交过来的任务请求。调用execute()方法添加一个请求......
  • 5、进程与线程
    进程与线程1、 进程是程序的一次动态执行过程,它经历了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程本身从产生、发展到消亡的过程2、 线程Thread是进程下......
  • Python3 多线程并发处理的返回值收集
    库函数threading背景去查询python3多线程,可以找到一大堆关于threading库的博客教程,但是多数是几个线程执行同一个函数(他们博客里各个线程传入的函数参数不同),且没有......
  • 【案例分享】跨机房ES同步实战
    作者:谢泽华​背景众所周知单个机房在出现不可抗拒的问题(如断电、断网等因素)时,会导致无法正常提供服务,会对业务造成潜在的损失。所以在协同办公领域,一种可以基于同城或异地......
  • Java线程中断机制
    在阅读AQS源码以及juc包很多基于AQS的应用源码过程中,会遇到很多interrupted相关的方法,这里复习一下java线程中断相关。要点:使用interrupt()中断一个线程,该方法只是标记中......
  • 跨机房ES同步实战
    作者:谢泽华背景众所周知单个机房在出现不可抗拒的问题(如断电、断网等因素)时,会导致无法正常提供服务,会对业务造成潜在的损失。所以在协同办公领域,一种可以基于同城或异地......
  • 万字干货|Synchronized关键字详解
    作者:小牛呼噜噜|https://xiaoniuhululu.com计算机内功、JAVA底层、面试、职业成长相关资料等更多精彩文章在公众号「小牛呼噜噜」前言大家好,我是呼噜噜,在之前的文章......