码迷,mamicode.com
首页 > 编程语言 > 详细

多线程之死锁、生产者与消费者模型以及线程池

时间:2021-06-30 18:01:58      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ice   ati   之间   子类   记录   管程   final   ror   强制   

死锁产生的四个必要条件
  • 互斥条件:一个资源每次只能被一个进程使用

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

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

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

实例
package com.yeyue.thread;
?
public class DeadLock {
   public static void main(String[] args) {
       new Makeup(0,"灰姑凉").start();
       new Makeup(1,"白雪公主").start();
  }
?
}
?
//口红
class Lipstick{
?
}
?
//镜子
class Mirror {
?
}
?
class Makeup extends Thread {
?
   //需要的资源只有一份,用static来保证只有一份
   static Lipstick lipstick = new Lipstick();
   static Mirror mirror = new Mirror();
?
   int choice;
   String girlName;
?
   Makeup(int choice, String girlName) {
       this.choice = choice;
       this.girlName = girlName;
  }
?
   @Override
   public void run() {
       try {
           makeup();
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
  }
?
   private void makeup() throws InterruptedException {
       if (choice == 0) {
           synchronized (lipstick) {
               System.out.println(this.girlName + "获得了口红的锁");
               Thread.sleep(1000);
               synchronized (mirror) {
                   System.out.println(this.girlName + "获得了镜子的锁");
              }
          }
      } else {
           synchronized (mirror) {
               System.out.println(this.girlName + "获得了镜子的锁");
               Thread.sleep(1000);
               synchronized (lipstick) {
                   System.out.println(this.girlName + "获得了口红的锁");
              }
          }
      }
  }
}
避免死锁
package com.yeyue.thread;
?
public class DeadLock {
   public static void main(String[] args) {
       new Makeup(0,"灰姑凉").start();
       new Makeup(1,"白雪公主").start();
  }
?
}
?
//口红
class Lipstick{
?
}
?
//镜子
class Mirror {
?
}
?
class Makeup extends Thread {
?
   //需要的资源只有一份,用static来保证只有一份
   static Lipstick lipstick = new Lipstick();
   static Mirror mirror = new Mirror();
?
   int choice;
   String girlName;
?
   Makeup(int choice, String girlName) {
       this.choice = choice;
       this.girlName = girlName;
  }
?
   @Override
   public void run() {
       try {
           makeup();
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
  }
?
   private void makeup() throws InterruptedException {
       if (choice == 0) {
           synchronized (lipstick) {
               System.out.println(this.girlName + "获得了口红的锁");
               Thread.sleep(1000);
              }
           synchronized (mirror) {
               System.out.println(this.girlName + "获得了镜子的锁");
          }
      } else {
           synchronized (mirror) {
               System.out.println(this.girlName + "获得了镜子的锁");
               Thread.sleep(1000);
              }
           synchronized (lipstick) {
               System.out.println(this.girlName + "获得了口红的锁");
          }
      }
  }
}
synchronized与lock的对比
  • lock是显示锁(手动开启和关闭锁,别忘记关锁)synchronized是隐式锁,除了作用域自动释放

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

  • 使用lock锁,jvm将花费较少的时间来调度线程,性能更好。而且具有更好的扩展性(提供更多的子类)

  • 优先使用顺序:

    lock>同步代码块(已经进入方法体,分配了相应资源)>同步方法(在方法体之外)

    实例
    package com.yeyue.thread;
    ?
    import java.util.concurrent.locks.ReentrantLock;
    ?
    public class TestLock {
       public static void main(String[] args) {
           TestLock2 testLock2 = new TestLock2();
    ?
           new Thread(testLock2).start();
           new Thread(testLock2).start();
           new Thread(testLock2).start();
      }
    }
    ?
    class TestLock2 implements Runnable{
    ?
       int ticketNums = 10;
       //定义lock锁
       private final ReentrantLock lock = new ReentrantLock();
    ?
       @Override
       public void run() {
           while (true){
               try{
                   lock.lock();
                   if(ticketNums>0){
                       try {
                           Thread.sleep(1000);
                      } catch (InterruptedException e) {
                           e.printStackTrace();
                      }
                       System.out.println(ticketNums--);
                  }else {
                       break;
                  }
              }finally {
                   lock.unlock();
              }
          }
      }
    }
生产者消费者模型-->利用缓冲区解决:管程法
package com.yeyue.thread;
?
//测试:生产者消费者模型-->利用缓冲区解决:管程法
?
//生产者,消费者,产品,缓冲区
public class TestPC {
   public static void main(String[] args) {
       SynContainer container = new SynContainer();
?
       new Productor(container).start();
       new Consumer(container).start();
?
  }
}
?
//生产者
class Productor extends Thread{
   SynContainer container;
?
   public Productor(SynContainer container){
       this.container = container;
  }
?
   //生产
   @Override
   public void run() {
       for (int i = 0; i < 100; i++) {
           container.push(new Chicken(i));
           System.out.println("生产了"+i+"只鸡");
           try {
               Thread.sleep(200);
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
  }
}
?
//消费者
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+"只鸡");
           try {
               Thread.sleep(200);
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
  }
}
?
//产品
class Chicken{
   int id ; //产品ID
?
   public Chicken(int id) {
       this.id = id;
  }
}
?
//缓冲区
class SynContainer {
?
   //容器大小
   Chicken[] chickens = new Chicken[10];
   //容器计数器
   int count = 0;
?
?
   //生产者放入产品
   public synchronized void push(Chicken chicken){
       //如果产品满了,就需要生产者等待消费者消费
       if(count==chickens.length) {
           //通知消费者消费,生产等待
           try {
               this.wait();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
       //如果没有满,我们就需要丢入产品
       chickens[count]=chicken;
       count++;
?
       //可以通知消费者消费了
       this.notifyAll();
  }
?
   //消费者消费产品
   public synchronized Chicken pop(){
       //判断能否消费
       if(count==0){
           //等待生产者生产,消费者等待
           try {
               this.wait();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
?
       //如果可以消费
       count--;
       Chicken chicken = chickens[count];
?
       //吃完了
       this.notifyAll();
       return chicken;
  }
?
?
?
?
?
?
?
?
?
?
?
?
}
测试:生产者消费者模型2-->信号灯法
package com.yeyue.thread;
?
//测试:生产者消费者模型2-->信号灯法
public class TestPC2 {
   public static void main(String[] args) {
       TV tv = new TV();
       new Player(tv).start();
       new Watcher(tv).start();
  }
}
?
//生产者:演员
class Player extends Thread{
   TV tv;
   public Player(TV tv){
       this.tv = tv;
  }
?
   //表演节目
   @Override
   public void run() {
       for (int i = 0; i < 20; i++) {
           if(i%2==0){
               this.tv.play("快乐大本营");
          }else{
               this.tv.play("抖音:记录美好生活");
          }
      }
  }
}
?
//消费者:观众
class Watcher extends Thread{
   TV tv;
   public Watcher(TV tv){
       this.tv = tv;
  }
?
   //观看
   @Override
   public void run() {
       for (int i = 0; i < 20; i++) {
           tv.watch();
      }
  }
}
?
//产品:节目
class TV {
   //演员表演,观众等待 T
   //观众观看,演员等待 F
   String voice; //表演的节目
   boolean flag = true;
?
   //表演
   public synchronized void play(String voice){
?
       //等待观众观看
       if (!flag){
           try {
               this.wait();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
?
       System.out.println("演员表演了:" + voice);
?
       this.notifyAll(); //通知观众观看
       this.voice = voice;
       this.flag = !this.flag;
  }
?
   //观看
   public synchronized  void watch(){
       if(flag){
           try {
               this.wait();
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
      }
       System.out.println("观看了"+voice);
?
       this.notifyAll(); //通知演员表演
       this.flag = !this.flag;
  }
?
}
线程池
package com.yeyue.thread;
?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
?
public class TestPool {
   public static void main(String[] args) {
       //1、创建服务,创建线程池
       //newFixedThreadPool 参数:线程池大小
       ExecutorService service = Executors.newFixedThreadPool(10);
?
       //执行
       service.execute(new MyThread());
       service.execute(new MyThread());
       service.execute(new MyThread());
       service.execute(new MyThread());
?
       //2、关闭链接
       service.shutdown();
?
  }
}
?
class MyThread implements Runnable{
?
   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
  }
}

 

多线程之死锁、生产者与消费者模型以及线程池

标签:ice   ati   之间   子类   记录   管程   final   ror   强制   

原文地址:https://www.cnblogs.com/shenyeanyue-study/p/14952177.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!