zoukankan      html  css  js  c++  java
  • 用生活例子来解释Java synchronized块

          今天满世界的微信小程序的新闻,大家都说对于Android原生程序有构成危险了,我也不想了,以后的事谁知道呢, 我还是好好执行一下今年的计划吧。  项目刚刚上线,最近没啥事,我一直感觉自己的Java基础不够扎实,于是就想恶补下一下基础。记得大学英语老师告诉我们,学习要学会炒冷饭,多重复。 我就先从Java多线程的知识再拿出来巩固下,话说无论是从事J2EE还是Android开发,如果对多线程的知识掌握的不好,无论是面试还是工作都说不过去的,至少你不敢说熟悉Java.

         我们都知道synchronized关键字可以让线程同步,但是如果用的位置不好,导致运行效率要降低很多。废话不多说,先上代码。

    public class Worker {
        
        private Random random=new Random();
        private ArrayList<Integer>  list1=new ArrayList<>();
        private ArrayList<Integer>  list2=new ArrayList<>();
    
        private synchronized void stageOne(){
            
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                list1.add(random.nextInt(100));
            
            
        }
        
        private  synchronized void stageTwo(){
            
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                list2.add(random.nextInt(100));
            
            
        }
        
        
        
        private void process(){
            for(int i=0;i<1000;i++){
                stageOne();
                stageTwo();
            }
        }
        
        public void test(){
              long start=System.currentTimeMillis();
              
              Thread t1=new Thread(new Runnable() {
                
                @Override
                public void run() {
                  process();                
                }
            });
              t1.start();
              
              Thread t2=new Thread(new Runnable() {
                  
                  @Override
                  public void run() {
                      process();
                      
                  }
              });
               t2.start();
                
              try {
                t1.join();
                t2.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
              
              long end = System.currentTimeMillis();
              
              System.out.println("耗时:"+(end-start));
              System.out.println("list1 size:"+list1.size()+"  list2 size:"+list2.size());
        }
    }

       耗时:5057
       list1 size:2000 list2 size:2000

     

    把代码改进后,代码如下:

    package cave;
    
    import java.util.ArrayList;
    import java.util.Random;
    
    public class Worker {
        
        private Random random=new Random();
        private ArrayList<Integer>  list1=new ArrayList<>();
        private ArrayList<Integer>  list2=new ArrayList<>();
        
        private Object lock1=new Object();
        private Object lokck2=new Object();
        
        
        
        
        private  void stageOne(){
            synchronized (lock1) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                list1.add(random.nextInt(100));
            }
                
            
            
        }
        
        private   void stageTwo(){
            synchronized (lokck2) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                list2.add(random.nextInt(100));
            }    
            
        }
        
        
        
        private void process(){
            for(int i=0;i<1000;i++){
                stageOne();
                stageTwo();
            }
        }
        
        public void test(){
              long start=System.currentTimeMillis();
              
              Thread t1=new Thread(new Runnable() {
                
                @Override
                public void run() {
                  process();                
                }
            });
              t1.start();
              
              Thread t2=new Thread(new Runnable() {
                  
                  @Override
                  public void run() {
                      process();
                      
                  }
              });
               t2.start();
                
              try {
                t1.join();
                t2.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
              
              long end = System.currentTimeMillis();
              
              System.out.println("耗时:"+(end-start));
              System.out.println("list1 size:"+list1.size()+"  list2 size:"+list2.size());
        }
                
    }

    耗时:2536
    list1 size:2000 list2 size:2000

    
    

    从耗时来看,改进后代码时间比之前少了近一半. 我这里stageOne和stageTwo方法代码比较简单,只有一个for循环。如果这个方法里代码有很多,其中一部分是耗时操作,你还把 synchronized关键字来修饰方法,那么耗时将会更多。所以涉及到的线程同步,synchronized所约束的范围越小越好,性能才会越高。这样说可能有点难以理解。我来打个比方吧,如果你去一个店里买衣服,看到一件衣服非常满意,就想去试一下衣服,这个时候正常情况下导购会告诉你试衣间在哪,让你过去试试衣服,你去了试衣间,然后把门关上,这个就相当于加synchronized关键字了。当然了,有的人进去不是去试衣服的,比如2015年的北京三里屯优衣库试衣间那一对男女是在玩耍,我们也管不了,对吧。不过,那个视频看得真是带劲,我还发给一个女生看了。试衣完毕,肯定出来了,其他人会进去锁上门,试衣服。这样进啊出啊进啊出啊,这个试衣间的锁就是相当于synchronized关键字。那么试想有一种情景:你去买衣服,当你要试衣服的时候,你告诉导购要把店面的大门关上(这个时候在外面大门加锁,相当于synchronized),其他人在外面等候,而且店面是上海南京东路步行街的一家店,人流量巨大。如果每个人试衣服都要求导购把店面大门关上,估计你下个月看不到这个店了,因为它关门倒闭了。你换个衣服这样折腾,这生意还能做下去吗?我估计是来了一个大明星,比如汤唯来到南京东路步行街买衣服,那大门估计真的要关上,不然多少男生要流口水啊,这个生意也没法做啊。总之,试衣服只要把试衣间的门锁上就好了,不用关上大门了。 

         好了,这么一说,你应该理解了为什么synchronized块比synchronized修饰方法性能高了吧,如果还想不通,就想一想你在店外面等着人家试衣服,如果一对男女进去试衣服,你想偷拍都不行啊,这多着急啊,我能理解你的心情!恩,记得只要在试衣间试衣服,坚决不出去。

     

  • 相关阅读:
    软件工程,实践作业1_团队博客
    软件工程,实践作业1
    c# excel 读写 64位操作系统 64位excel
    pyfits fits图像区域选择
    python numpy中sum()时出现负值
    python 中模块的版本号
    numpy rand函数的应用
    python 字符串是否包含某个子字符串
    python 字符串格式化
    python 让异常名称显示出来
  • 原文地址:https://www.cnblogs.com/tleopard/p/6265701.html
Copyright © 2011-2022 走看看