• Java学习笔记——35多线程02


    线程同步

    卖票案例

    public class SellTicket implements Runnable{
        private int tickets=10;
        @Override
        public void run(){
            while (true){
                if(tickets>0){
                    System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张票");
                    tickets--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    public class SellTicketDemo {
        public static void main(String[] args) {
            SellTicket st= new SellTicket();
            Thread t1=new Thread(st,"李昊");
            Thread t2=new Thread(st,"朱长坤");
            Thread t3=new Thread(st,"杨天伦");
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    相同的票出现了多次
    出现了负数票
    原因是线程执行的随机性导致的

    同步代码块

    锁多条语句操作共享数据,可以使用同步代码块实现

    格式

    	syschronized(任意对象){
    		多条语句操作共享数据的代码
    	}
    
    • 1
    • 2
    • 3
    public class SellTicket implements Runnable{
        private int tickets=10;
        private Object obj=new Object();
        @Override
        public void run(){
            while (true){
                synchronized(obj){
                    if(tickets>0){
                        System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张票");
                        tickets--;
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    同步的好处和弊端

    • 好处:解决了多线程的数据安全问题
    • 弊端:当线程很多时,因为每个线程都会去判断同步上的锁,很耗费资源,会降低运行速率
    • 同步方法

      • 同步方法:就是把synchronized关键字加到方法上

      格式

      	修饰符 synchronized 返回值类型 方法名(方法参数){
      	
      	}
      
      • 1
      • 2
      • 3
      public class SellTicket implements Runnable{
          private int tickets=10;
      
          private int x=0;
          @Override
          public void run(){
              while (true){
                  if(x%2==0){
                      synchronized(this){
                          if(tickets>0){
                              System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                              tickets--;
                              try {
                                  Thread.sleep(100);
                              } catch (InterruptedException e) {
                                  throw new RuntimeException(e);
                              }
                          }
                      }
                  }
                  else{
                      sellTicket();
                  }
                  x++;
              }
          }
          private synchronized void sellTicket(){
              if(tickets>0){
                  System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                  tickets--;
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38

      同步方法的锁对象是this

      • 同步j静态方法:就是把synchronized关键字加到静态方法上
        同步静态方法的锁对象是 类名.class
      public class SellTicket implements Runnable{
          private static int tickets=10;
      
          private int x=0;
          @Override
          public void run(){
              while (true){
                  if(x%2==0){
                      synchronized(SellTicket.class){
                          if(tickets>0){
                              System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                              tickets--;
                              try {
                                  Thread.sleep(100);
                              } catch (InterruptedException e) {
                                  throw new RuntimeException(e);
                              }
                          }
                      }
                  }
                  else{
                      sellTicket();
                  }
                  x++;
              }
          }
          private static synchronized void sellTicket(){
              if(tickets>0){
                  System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
                  tickets--;
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
              }
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39

      线程安全的类

      StringBuffer

      • 线程安全 ,可变的字符序列
      • 从版本JDK5开始,被StringBuilder替代。通常应该使用StringBuilder(非线程安全的)类,因为它支持所有相同的操作,并且更快,因为它不执行同步

      Vector

      从Java 2平台v1.2开始,该类改进了List接口,使其成为JavaCollections Framework的成员。与新的集合实现不同,Vector被同步。如果不需要线程安全的实现,建议使用ArrayList代替Vector

      Hashtable

      • 该类实现了一个哈希表,它将键映射到值。任何非null对象都可以用作键或者值
      • 从Java 2平台v1.2开始,该类进行了改进,实现了Map接口,使其成为JavaCollections Framework的成员。与新的集合实现不同,Hashtable被同步。如果不需要线程安全的实现,建议使用HashMap代替Hashtable

      **Collections.synchronizedList()**可返回线程安全的ArrayList
      同理map也可以Collections.synchronizedMap()

      Lock锁

      为了更清晰地表达如何加锁和释放锁,JDK5后提供了一个新的锁对象Lock

      Lock提供了比使用synchronized方法和语句更为广泛的锁定操作
      Lock中获得锁和释放锁的方法:

      • void lock():获得锁
      • void unlock():释放锁

      Lock接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化

      构造方法:ReentrantLock():创建一个ReentrantLock的实例

      public class SellTicket implements Runnable{
          private int tickets=20;
          private Lock lock=new ReentrantLock();
          @Override
          public void run(){
              while (true){
                  try{
                      lock.lock();
                      if (tickets>0){
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              throw new RuntimeException(e);
                          }
                          System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets+"张av");
                          tickets--;
                      } 
                  }finally {
                      lock.unlock(); 
                  }
                  
              }
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
  • 相关阅读:
    六、主存储器管理,计算机操作系统教程,第四版,左万利,王英
    代码随想录 Day13 二叉树 LeetCode T104 二叉树的最大深度 T111 二叉树的最小深度 T222完全二叉树的节点个数
    uni-app安卓appNFC读卡
    Diffusion Models & CLIP
    Ubuntu 22.04 一次及其繁琐的 允许 Traceroute 探测漏洞修复之旅
    S7-200SMART PLC Modbus TCP通信(多服务器多从站轮询)
    16. Java字符串拼接的低层原理
    9.jvm调优相关工具-java自带
    net+蛋糕销售网站 毕业设计-附源码090918
    多功能纳米酶Ag/PANI|柔性衬底纳米ZnO酶|铑片纳米酶|Ag-Rh合金纳米颗粒纳米酶|铱钌合金/氧化铱仿生纳米酶
  • 原文地址:https://blog.csdn.net/Lz0113/article/details/132696487