线程同步(synchronized)(重点)

线程同步(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();)
posted @ 2022-12-08 15:50  醉读付人心  阅读(27)  评论(0)    收藏  举报