摸鱼少学习多

day27- 同步方法

同步方法

死锁的概念

  1. 互斥条件:一个资源每次只能被一个进程使用

  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放

  3. 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺

  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系

synchronized 方法

使用synchronized方法和synchronized块

每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行会独占该锁,知道该方法返回才释放该锁

lock方法

定义lock锁,在使用同步资源前加锁,在使用结束后释放该锁

 
1 //定义lock锁
2  private final ReentrantLock lock = new ReentrantLock();

 

加锁

1  lock.lock();//加锁

 

解锁

 lock.unlock();//解锁

 

一般配合try catch使用,解锁放在finally中

复制代码
 1  //测试lock锁
 2  public class TestLock {
 3      public static void main(String[] args) {
 4          TestLock2 testLock2 = new TestLock2();
 5          new Thread(testLock2).start();
 6          new Thread(testLock2).start();
 7          new Thread(testLock2).start();
 8      }
 9  }
10 11  class TestLock2 implements Runnable{
12      int tickstnum =10;
13      //定义lock锁
14      private final ReentrantLock lock = new ReentrantLock();
15      @Override
16      public void run() {
17          while (true){
18 19              try {
20                  lock.lock();//加锁
21 22                  if (tickstnum > 0) {
23                      try {
24                          Thread.sleep(1000);
25                      } catch (InterruptedException e) {
26                          e.printStackTrace();
27                      }
28                      System.out.println(tickstnum--);
29                  } else {
30                      break;
31                  }
32              }finally {
33                  lock.unlock();//解锁
34              }
35          }
36 37      }
38  }
复制代码

 

synchronized与lock

  1. lock是显式锁,手动开启和关闭,synchronized是隐式锁,出了作用域自动释放

  2. lock只有代码锁,synchronized有代码块和方法锁

  3. lock性能更好

利用缓冲区解决,管程法

定义缓冲区,定义拿取函数

使用synchronized定义

 
复制代码
 1 //缓冲区
 2  class SynContainer{
 3      //容器大小
 4      Chicken[] chickens = new Chicken[10];
 5      //容器计数器
 6      int count = 0;
 7      //生产者放入产品
 8      public synchronized void push(Chicken chicken) throws InterruptedException {
 9          //如果容器满了 需要等待消费者消费
10          if(count == chickens.length){
11              //通知消费者等待
12              this.wait();
13          }
14          //如果没满 可以丢入产品
15          chickens[count] = chicken;
16          count++;
17          //通知消费者消费
18          this.notifyAll();
19      }
20 21 22      //消费者取走产品
23      public synchronized Chicken pop() throws InterruptedException {
24          //判断能否消费
25          if (count == 0){
26              //等待生产者生产
27              this.wait();
28          }
29          //如果可以生产
30          count--;
31          Chicken chicken = chickens[count];
32 33 34          //吃完了 通知生产者生产
35          this.notifyAll();
36          return chicken;
37      }
38  }
复制代码

 

定义生产者消费者进程 通过缓冲区调用该进程

 
复制代码
 1 //生产者消费者模型-> 利用缓冲区解决:管程法
 2  public class TestPC {
 3      public static void main(String[] args) {
 4          SynContainer container = new SynContainer();
 5          new Producer(container).start();
 6          new Consumer(container).start();
 7      }
 8  }
 9 10  //生产者
11  class Producer extends Thread{
12      SynContainer container;
13      public Producer(SynContainer container){
14          this.container = container;
15      }
16      //生产
17      @Override
18      public void run() {
19          for (int i = 0; i < 100; i++) {
20              System.out.println("生产了"+i+"只鸡");
21              try {
22                  container.push(new Chicken(i));
23              } catch (InterruptedException e) {
24                  e.printStackTrace();
25              }
26          }
27      }
28  }
29 30  //消费者
31  class Consumer extends Thread{
32      SynContainer container;
33      public Consumer(SynContainer container){
34          this.container = container;
35      }
36      //消费
37      @Override
38      public void run() {
39          for (int i = 0; i < 100; i++) {
40              try {
41                  System.out.println("消费了-->"+container.pop().id+"只鸡");
42              } catch (InterruptedException e) {
43                  e.printStackTrace();
44              }
45          }
46      }
47  }
48 49  //产品
50  class Chicken{
51      int id;
52 53      public Chicken(int id) {
54          this.id = id;
55      }
56  }
复制代码

 

 

表演者与观众同步进程

复制代码
 1  public class TestPc2 {
 2      public static void main(String[] args) {
 3          TV tv = new TV();
 4          new Player(tv).start();
 5          new Watcher(tv).start();
 6      }
 7  }
 8  9  //生产者->演员
10  class Player extends Thread{
11      TV tv;
12      public Player(TV tv){
13          this.tv = tv;
14      }
15      @Override
16      public void run() {
17          for (int i = 0; i < 20; i++) {
18              if(i%2==0){
19                  tv.play("快乐大本营");
20              }else{
21                  tv.play("抖音");
22              }
23          }
24      }
25  }
26  //消费者->观众
27  class Watcher extends  Thread{
28      TV tv;
29      public Watcher(TV tv){
30          this.tv = tv;
31      }
32      @Override
33      public void run() {
34          for (int i = 0; i < 20; i++) {
35              tv.watch();
36          }
37      }
38  }
39  //产品->节目
40  class TV{
41      String name;
42      boolean flag = true;
43 44      //表演
45      public synchronized void play(String name){
46          if (!flag){
47              try {
48                  this.wait();
49              } catch (InterruptedException e) {
50                  e.printStackTrace();
51              }
52          }
53          System.out.println("表演了 "+name);
54          this.notifyAll();
55          this.name = name;
56          this.flag = !this.flag;
57 58      }
59      //观看
60      public synchronized void watch(){
61          if(flag){
62              try {
63                  this.wait();
64              } catch (InterruptedException e) {
65                  e.printStackTrace();
66              }
67          }
68          System.out.println("观看了 "+name);
69          this.notifyAll();
70          this.flag = !this.flag;
71 72      }
73  }
复制代码

 

线程池

复制代码
 1  //测试线程池
 2  public class TestPool {
 3      public static void main(String[] args) {
 4          //1.创建线程池
 5          //newFixedThreadPool参数为:线程池大小
 6          ExecutorService service = Executors.newFixedThreadPool(10);
 7  8          service.execute(new MyThread());
 9          service.execute(new MyThread());
10          service.execute(new MyThread());
11          service.execute(new MyThread());
12          //2.关闭连接
13          service.shutdown();
14      }
15  }
16 17 18  class MyThread implements Runnable{
19      @Override
20      public void run() {
21 22              System.out.println(Thread.currentThread().getName());
23 24      }
25  }
复制代码

 

 
posted @   北海之上  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
/* 粒子吸附*/
点击右上角即可分享
微信分享提示