精华内容
下载资源
问答
  • GIT代码仓库管理规范

    2020-11-03 16:10:57
    什么代码管理规范? 讲个小故事,王者荣耀或者英雄联盟都玩过吧。我们要gank(游戏中一个或几个的游戏角色行动,对对方的游戏角色进行偷袭、包抄、围杀)对面中单选手,于是约定策略为 我方中单负责勾引,牵扯...

    为什么要做代码管理规范?

    讲个小故事,王者荣耀或者英雄联盟都玩过吧。我们要gank(游戏中一个或几个的游戏角色行动,对对方的游戏角色进行偷袭、包抄、围杀)对面中单选手,于是约定策略为

    1. 我方中单负责勾引,牵扯住对方中单
    2. 我方打野埋伏在草丛,等待辅助过来
    3. 辅助选手从下路赶过来支援

    如果各位选手按照策略进行会对敌方进行一波很好的击杀,但由于打野沉不住性子,在埋伏的过程中,去了对方野区反了波野怪被看到了位置。对面选手来了波反蹲,我方其它选手并不知情,毅然选择开战,结果可想而知被地方反杀。
    代码管理也是一个多人合作的才能达到互利共生,这就需要有一个约定的策略,才能保证项目能能够顺利进行。

    一、commit规范

    规范的commit日志,能让人一眼扫出关键信息。坏的日志让人看的不明所以,一头雾水,特别是在需要代码回滚的情况下。曾经有个团队成员一直用以下方式提交,后来有一次她的代码需要回滚,这种日志的情况下,回滚了三四次都没有找到正确的节点。多次劝她无果,现在这位同事已经被公司接触劳动合同了。

    Commit message 提交规范,包括type(必需) + subject(必需),提供更多的历史信息,方便快速浏览。可过滤某些信息(比如构建安装包);

    #1 type
    
    #主要type
    
    feat:新功能
    fix: 修补bug
    
    #特殊type
    docs:文档(document)
    style:格式(不影响代码运行的变动)
    refactor:重构(既不是新功能,也不是修改bug的代码变动)
    test:增加测试
    build:构造工具的或者外部依赖的改动,例如webpack,npm
    chore: 不修改src或者test的其余修改,例如构建过程或辅助工具的变动
    
    #2 subject
    
    subject是 commit 目的的简短描述,不超过50个字符。
    

    举例如下:

    1. 新增功能
    2. 修补bug
      带来的好处:
      • 可读性好,清晰,不必深入看代码即可了解当前commit的作用。
      • 为 Code Reviewing做准备
      • 方便跟踪工程历史
      • 让其他的开发者在运行 git blame 的时候清晰明了
      • 提高项目的整体质量,提高个人工程素质

    二、分支管理规范

    分支管理规范。

    1. 当前任务开发分支为develop分支,develop作为开发分支以及提测分支使用。如有新的上线需手动将master分支代码合并到develop分支
    2. develop分支测试通过,从develop切到当前版本分支比如:v2.0(下面都以v2.0举例),用v2.0作为预发分支以及上线分支。
    3. v2.0在预发环境测试通过后,可直接作为上线分支上线。
    4. v2.0分支上线成功之后,需合并到master分支
    5. 线上bug修改,修复v2.0的线上bug,可切新的分支v2.1,依次累加等。

    git分支管理流程图如下:
    在这里插入图片描述

    三、总结

    好的Git管理方法,能极大的提高团队工作效率,避免提交错乱。

    参考:https://www.processon.com/diagrams/new#template

    如有问题请联系我~

    欢迎加入QQ群:
    在这里插入图片描述

    展开全文
  • 子应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新</li><li>独立运行时 每个子应用之间状态隔离,运行时状态不共享</li></ul> 微前端架构旨在解决单体应用在一个相对长的...
  • 3. 项目仓库中所需的组件通过 bower 安装进来的,组件代码存放在内部的 gitlab 仓库上 4. 最后的打包发布也通过 Node 工具完成的,这些工具都一键安装的 5. 项目和组件的初始模板通过基于 Yeoman ...
  • 枸杞的由来和技术栈

    2021-01-02 15:11:32
    靠 React Native 本身想构建一个稍大型的 App 不现实的。 如果没有原生语言开发者,对于枸杞和系统资源有交互这样的中小型项目,React Native 原生插件社区能提供的帮助也不多。在去年的时候由于...
  • 当张三回来后再报帐,这时先一笔“收款”将张三预领的出差费冲平。然后再一笔费用,即可为张三报帐。 $27.如果你用的hpdj200打印机,当出现打印无法创建的提示时? #27.当遇到这种情况时,因为软件狗...
  • eas供应链dep案例集

    2017-11-18 22:32:39
    新增及调整字段 EASSCMA1P0103 采购收货单分录增加单价金额字段 用户的采购收货单是关键单据,需要通过收货单关联生成和查询到票情况,但收货单上没有单价金额字段,应付单无法从它取价。 因采购收货单分录上本身已...
  • Java基础-->多线程

    2014-10-16 10:04:36
    一、概述: 1、线程是什么呢? 我们先来说一说比较熟悉的进程吧,之后就比较容易理解线程了。所谓进程,就是一个正在执行(进行)中的程序。每一个进程的执行都有一个执行顺序,或者...个比方说,在仓库搬运货

    一、概述:

    1、线程是什么呢?

    我们先来说一说比较熟悉的进程吧,之后就比较容易理解线程了。所谓进程,就是一个正在执行(进行)中的程序。每一个进程的执行都有一个执行顺序,或者说是一个控制单元。简单来说,就是你做一件事所要进行的一套流程。线程,就是进程中的一个独立的控制单元;也就是说,线程是爱控制着进程的执行。一个进程至少有一个线程,并且线程的出现使得程序要有效率。打个比方说,在仓库搬运货物,一个人搬运和五个人搬运效率是不一样的,搬运货物的整个程序,就是进程;每一个人搬运货物的过程,就是线程。

    2、java中的线程:

    在java中,JVM虚拟机启动时,会有一个进程为java.exe,该程序中至少有一个线程负责java程序的执行;而且该程序运行的代码存在于main方法中,该线程称之为主线程。其实,JVM启动时不止有一个线程(主线程),由于java是具有垃圾回收机制的,所以,在进程中,还有负责垃圾回收机制的线程。

    3、多线程的意义:

    透过上面的例子,可以看出,多线程有两方面的意义:

    1)提高效率。   2)清除垃圾,解决内存不足的问题。

    二、自定义线程:

    线程有如此的好处,那要如何才能通过代码自定义一个线程呢?其实,线程是通过系统创建和分配的,java是不能独立创建线程的;但是,java是可以通过调用系统,来实现对进程的创建和分配的。java作为一种面向对象的编程语言,是可以将任何事物描述为对象,从而进行操作的,进程也不例外。我们通过查阅API文档,知道java提供了对线程这类事物的描述,即Thread类。创建新执行线程有两种方法

    一)创建线程方式一:继承Thread类。

    1、步骤:

    第一、定义类继承Thread。

    第二、复写Thread类中的run方法。

    第三、调用线程的start方法。分配并启动该子类的实例。

              start方法的作用:启动线程,并调用run方法。

    1. <span style="font-family: Arial; ">class Demo extends Thread  
    2. {  
    3.     public void run()  
    4.     {  
    5.         for (int i=0;i<60;i++)  
    6.             System.out.println(Thread.currentThread().getName() + "demo run---" + i);  
    7.     }  
    8. }  
    9. class Test2  
    10. {  
    11.     public static void main(String[] args)   
    12.     {  
    13.         Demo d1 = new Demo();//创建一个对象就创建好了一个线程  
    14.         Demo d2 = new Demo();  
    15.         d1.start();//开启线程并执行run方法  
    16.         d2.start();  
    17.         for (int i=0;i<60;i++)  
    18.             System.out.println("Hello World!---" + i);  
    19.     }  
    20. }</span>  

    2、运行特点:

    A.并发性:我们看到的程序(或线程)并发执行,其实是一种假象。有一点需要明确:;在某一时刻,只有一个程序在运行(多核除外),此时cpu是在进行快速的切换,以达到看上去是同时运行的效果。由于切换时间是非常短的,所以我们可以认为是在并发进行。

    B.随机性:在运行时,每次的结果不同。由于多个线程都在获取cpu的执行权,cpu执行到哪个线程,哪个线程就会执行。可以将多线程运行的行为形象的称为互相抢夺cpu的执行权。这就是多线程的特点,随机性。执行到哪个程序并不确定。

    3、覆盖run方法的原因:

    1)Thread类用于描述线程。该类定义了一个功能:用于存储线程要运行的代码,该存储功能即为run方法。也就是说,Thread类中的run方法用于存储线程要运行的代码,就如同main方法存放的代码一样。

    2)复写run的目的:将自定义代码存储在run方法中,让线程运行要执行的代码。直接调用run,就是对象在调用方法。调用start(),开启线程并执行该线程的run方法。如果直接调用run方法,只是将线程创建了,但未运行。

    二)创建线程方式二:实现Runnable接口

    1、步骤:

    第一、定义类实现Runnable接口。

    第二、覆盖Runnable接口中的run方法。

    第三、通过Thread类建立线程对象。要运行几个线程,就创建几个对象。

    第四、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。

    第五、调用Thread类的start方法开启线程,并调用Runnable接口子类的run方法。

    1. <span style="font-family: Arial; ">  
    2. //多个窗口同时卖票  
    3. class Ticket implements Runnable  
    4. {  
    5.     private int tic = 20;  
    6.     public void run()  
    7.     {  
    8.         while(true)  
    9.         {  
    10.             if (tic > 0)  
    11.                 System.out.println(Thread.currentThread().getName() + "sale:" + tic--);  
    12.         }  
    13.     }  
    14. }  
    15.   
    16. class  TicketDemo  
    17. {  
    18.     public static void main(String[] args)   
    19.     {  
    20.         Ticket t = new Ticket();  
    21.         Thread t1 = new Thread(t);//创建一个线程  
    22.         Thread t2 = new Thread(t);//创建一个线程  
    23.         Thread t3 = new Thread(t);//创建一个线程  
    24.         Thread t4 = new Thread(t);//创建一个线程  
    25.         t1.start();  
    26.         t2.start();  
    27.         t3.start();  
    28.         t4.start();  
    29.     }  
    30. }  
    31. </span>  

    2、说明:

    A.步骤2覆盖run方法:将线程要运行的代码存放在该run方法中。

    B.步骤4:为何将Runnable接口的子类对象传给Thread构造函数。因为自定义的run方法所属对象为Runnable接口的子类对象,所以让线程指定对象的run方法,就必须明确该run方法所属的对象。

    三)实现方式与继承方式有何区别:

    1、实现方式:避免了单继承的局限性。

                 在定义线程时,建议使用实现方式。

    2区别:

    继承Thread:线程代码存放在Thread子类的run方法中。

    实现Runnable:线程代码存在接口的子类run方法中。

    需要注意的是:局部变量在每一个线程中都独有一份。

    四)Thread类中的一些方法简介:

    1、获取线程名称:getName()

    每个线程都有自己默认的名称,获取格式:对象.getName();打印后,显示为:Thread-编号(从0开始),也就是说,线程一为:Thread-0,线程二为:Thread-1。也可以获取当前线程对象的名称,通过currentThread().getName()。如上面方式二的结果为


    2、设置线程名称:setName()或构造函数

    可以通过setName()设置线程名称,或者通过含有参数的构造函数直接显式初始化线程的名称,如Test(String name)。

    三、线程的运行状态

    线程运行状态可用如下图示说明:


    需要说明的是:

    A.阻塞状态:具备运行资格,但是没有执行权,必须等到cpu的执行权,才转到运行状态,。

    B.冻结状态:放弃了cpu的执行资格,cpu不会将执行权分配给这个状态下的线程,必须被唤醒后,此线程要先转换到阻塞状态,等待cpu的执行权后,才有机会被执行到。

    四、多线程的安全问题:

    在那个简单的卖票小程序中,发现打印出了0、-1、-2等错票,也就是说这样的多线程在运行的时候是存在一定的安全问题的。

    为什么会出现这种安全问题呢?

    原因是当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还未执行完,另一线程就参与进来执行了,导致共享数据发生错误。以也就是说,由于cpu的快速切换,当执行线程一时,tic为1了,执行到if (tic > 0)的时候,cpu就可能将执行权给了线程二,那么线程一就停在这条语句了,tic还没减1,仍为1;线程二也判断if (tic > 0)是符合的,也停在这,以此类推。当cpu再次执行线程一的时候,打印的是1号,执行线程二的时候,是2号票,以此类推,就出现了错票的结果。其实就是多条语句被共享了,如果是一条语句,是不会出现此种情况的。

    那么该如何解决呢?

    对于多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可参与执行,就不会出现问题了。Java对于多线程的安全问题,提供了专业的解决方式,即同步代码块,可操作共享数据。

    1、同步代码块

    格式:

    1. <span style="font-family: Arial; ">  
    2. synchronized(对象)//对象称为锁旗标  
    3. {  
    4.     需要被同步的代码  
    5. }</span><span style="font-family: SimSun; font-size: 14px; ">  
    6. </span>  
    其中的对象如同锁,持有锁的线程可在同步中执行,没有锁的线程,即使获得cpu的执行权,也进不去,因为没有获取锁,是进不去代码块中执行共享数据语句的。

    1)同步的前提:

    A.必须有两个或两个以上的线程

    B.必须保证同步的线程使用同一个锁。必须保证同步中只能有一个线程在运行。

    好处与弊端:解决了多线程的安全问题。多个线程需要判断锁,较为消耗资源。

    示例:

    1. <span style="font-family: Arial; ">class Ticket implements Runnable  
    2. {  
    3.     private int tic = 100;  
    4.     Object obj = new Object();  
    5.     public void run()  
    6.     {  
    7.         while(true)  
    8.         {  
    9.             synchronized(obj)//任意的一个对象  
    10.             {  
    11.                 //此两句为共享语句  
    12.                 if (tic > 0)  
    13.                     System.out.println(Thread.currentThread().getName() + "sale:" + tic--);  
    14.             }     
    15.         }  
    16.     }  
    17. }  
    18.   
    19. class  TicketDemo  
    20. {  
    21.     public static void main(String[] args)   
    22.     {  
    23.         Ticket t = new Ticket();  
    24.         Thread t1 = new Thread(t,"1");//创建第一个线程  
    25.         Thread t2 = new Thread(t,"2");//创建第二个线程  
    26.         //开启线程  
    27.         t1.start();  
    28.         t2.start();  
    29.     }  
    30. }  
    31.   
    32. </span>  

    2、同步函数

    同步函数就是将修饰符synchronized放在返回类型的前面,下面通过同步函数给出多线程安全问题的具体解决方案:

    1)目的:判断程序中是否有安全问题,若有,该如何解决。

    2)解决:第一、明确哪些代码是多线程的运行代码

                      第二、明确共享数据

                      第三、明确多线程运行代码中,哪些语句是操作共享数据的。

    示例:

    1. <span style="font-family: Arial; ">class Bank  
    2. {  
    3.     private int sum;//共享数据  
    4.     //run中调用了add,所以其也为多线程运行代码  
    5.     public synchronized void add(int n)//同步函数,用synchronized修饰  
    6.     {  
    7.         //这有两句操作,是操作共享数据的  
    8.         sum += n;  
    9.             System.out.println("sum" + sum);  
    10.     }  
    11. }  
    12.   
    13. class Cus implements Runnable  
    14. {  
    15.     private Bank b = new Bank();//共享数据  
    16.     //多线程运行代码run  
    17.     public void run()  
    18.     {  
    19.         for (int i=0;i<3;i++)  
    20.         {  
    21.             b.add(100);//一句,不会分开执行,所以没问题  
    22.         }  
    23.     }  
    24. }  
    25.   
    26. class BankDemo   
    27. {  
    28.     public static void main(String[] args)   
    29.     {  
    30.         Cus c = new Cus();  
    31.         Thread t1 = new Thread(c);  
    32.         Thread t2 = new Thread(c);  
    33.         t1.start();  
    34.         t2.start();  
    35.     }  
    36. }  
    37. </span>  

    五、同步函数中的锁:

    1、非静态同步函数中的锁---> this

    函数需被对象调用,那么函数都有一个所属的对象引用,就是this,因此同步函数使用的锁为this。测验如下:

    1. <span style="font-family: Arial; ">  
    2. class Ticket implements Runnable  
    3. {  
    4.     private int tic = 100;  
    5.     boolean flog = true;  
    6.     public void run()  
    7.     {  
    8.         if (flog)  
    9.         {  
    10.             //线程一执行  
    11.             while(true)  
    12.             {  
    13.                 //如果对象为obj,则是两个锁,是不安全的;换成this,为一个锁,会安全很多  
    14.                 synchronized(this)  
    15.                 {  
    16.                     if (tic > 0)  
    17.                         System.out.println(Thread.currentThread().getName() + "--cobe--:" + tic--);  
    18.                 }  
    19.             }  
    20.         }  
    21.         //线程二执行  
    22.         else  
    23.             while(true)  
    24.                 show();  
    25.     }  
    26.     public synchronized void show()  
    27.     {  
    28.         if (tic > 0)  
    29.             System.out.println(Thread.currentThread().getName() + "----show-----:" + tic--);  
    30.     }  
    31. }  
    32.   
    33. class ThisLockDemo  
    34. {  
    35.     public static void main(String[] args)   
    36.     {  
    37.         Ticket t = new Ticket();  
    38.         Thread t1 = new Thread(t);//创建一个线程  
    39.         Thread t2 = new Thread(t);//创建一个线程  
    40.         t1.start();  
    41.         t.flog = false;//开启线程一,即关闭if,让线程二执行else中语句  
    42.         t2.start();  
    43.     }  
    44. }</span>  

    让线程一执行打印cobe的语句,让线程二执行打印show的语句。如果对象换位另一个对象obj,那将是两个锁,因为在主函数中创建了一个对象即Ticket t = new Ticket();,线程会共享这个对象调用的run方法中的数据,所以都是这个t对象在调用,那么,其中的对象应为this;否则就破坏了同步的前提,就会出现安全问题。

    2、静态同步函数中的锁:

    如果同步函数被静态修饰后,经验证,使用的锁不是this了,因为静态方法中不可定义this,所以,这个锁不再是this了。静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象:类名.class;该对象的类型是Class。

    所以静态的同步方法使用的锁是该方法所在类的字节码文件对象,即类名.class。

    示例:

    1. <span style="font-family: Arial; ">class Ticket implements Runnable  
    2. {  
    3.     //私有变量,共享数据  
    4.     private static int tic = 100;  
    5.     boolean flog = true;  
    6.     public void run()  
    7.     {  
    8.         //线程一执行  
    9.         if (flog)  
    10.         {  
    11.             while(true)  
    12.             {  
    13.                 synchronized(Ticket.class)//不再是this了,是Ticket.class  
    14.                 {  
    15.                     if (tic > 0)  
    16.                         System.out.println(Thread.currentThread().getName() + "--obj--:" + tic--);  
    17.                 }  
    18.             }  
    19.         }  
    20.         //线程二执行  
    21.         else  
    22.             while(true)  
    23.                 show();  
    24.     }  
    25.     public static synchronized void show()  
    26.     {  
    27.         if (tic > 0)  
    28.             System.out.println(Thread.currentThread().getName() + "----show-----:" + tic--);  
    29.     }  
    30. }  
    31.   
    32. class StaticLockDemo  
    33. {  
    34.     public static void main(String[] args)   
    35.     {  
    36.         Ticket t = new Ticket();  
    37.         Thread t1 = new Thread(t);//创建第一个线程  
    38.         Thread t2 = new Thread(t);//创建第二个线程  
    39.         t1.start();  
    40.         t.flog = false;  
    41.         t2.start();  
    42.     }  
    43. }  
    44. </span>  

    在之前,也提到过关于多线程的安全问题的相关知识,就是在单例设计模式中的懒汉式中,用到了锁的机制。

    具体请看单例设计模式中的内容:http://blog.csdn.net/shengfeixiang/article/details/8592722


    六、多线程间的通信:

    多线程间通信是线程之间进行交互的方式,简单说就是存储资源和获取资源。比如说仓库中的货物,有进货的,有出货的。还比如生产者和消费者的例子。这些都可以作为线程通信的实例。那么如何更好地实现通信呢?先看下面的代码:

    1. /* 
    2. 线程间通信: 
    3.  
    4. 等待唤醒机制:升级版 
    5.  
    6. 生产者消费者  多个 
    7.  
    8. */  
    9. import java.util.concurrent.locks.*;  
    10.   
    11. class ProducerConsumerDemo{  
    12.     public static void main(String[] args){  
    13.         Resouse r = new Resouse();  
    14.         Producer p = new Producer(r);  
    15.         Consumer c = new Consumer(r);  
    16.         Thread t1 = new Thread(p);  
    17.         Thread t2 = new Thread(c);  
    18.         Thread t3 = new Thread(p);  
    19.         Thread t4 = new Thread(c);  
    20.         t1.start();  
    21.         t2.start();  
    22.         t3.start();  
    23.         t4.start();  
    24.     }  
    25. }  
    26.   
    27. class Resouse{  
    28.     private String name;  
    29.     private int count = 1;  
    30.     private boolean flag =  false;   
    31.     private Lock lock = new ReentrantLock();  
    32.     private Condition condition_P = lock.newCondition();  
    33.     private Condition condition_C = lock.newCondition();  
    34. //要唤醒全部,否则都可能处于冻结状态,那么程序就会停止。这和死锁有区别的。  
    35.     public void set(String name)throws InterruptedException{  
    36.         lock.lock();  
    37.         try{  
    38.             while(flag)//循环判断,防止都冻结状态  
    39.                 condition_P.await();  
    40.             this.name = name + "--" + count++;  
    41.             System.out.println(Thread.currentThread().getName() + "..生成者--" + this.name);  
    42.             flag = true;  
    43.             condition_C.signal();  
    44.         }finally{  
    45.             lock.unlock();//释放锁的机制一定要执行  
    46.         }         
    47.     }  
    48.     public void out()throws InterruptedException{  
    49.         lock.lock();  
    50.         try{  
    51.             while(!flag)//循环判断,防止都冻结状态  
    52.                 condition_C.await();  
    53.             System.out.println(Thread.currentThread().getName() + "..消费者." + this.name);  
    54.             flag = false;  
    55.             condition_P.signal();//唤醒全部  
    56.         }finally{  
    57.             lock.unlock();  
    58.         }  
    59.     }  
    60. }  
    61.   
    62. class Producer implements Runnable{  
    63.     private Resouse r;  
    64.     Producer(Resouse r){  
    65.         this.r = r;  
    66.     }  
    67.     public void run(){  
    68.         while(true){  
    69.             try{  
    70.                 r.set("--商品--");  
    71.             }catch (InterruptedException e){}  
    72.         }  
    73.     }  
    74. }  
    75.   
    76. class Consumer implements Runnable{  
    77.     private Resouse r;  
    78.     Consumer(Resouse r){  
    79.         this.r = r;  
    80.     }  
    81.     public void run(){  
    82.         while(true){  
    83.             try{  
    84.                 r.out();  
    85.             }catch (InterruptedException e){}  
    86.         }  
    87.     }  
    88. }  


    一)等待唤醒机制:

    1、显式锁机制和等待唤醒机制:

    在JDK 1.5中,提供了改进synchronized的升级解决方案。将同步synchronized替换为显式的Lock操作,将Object中的wait,notify,notifyAll替换成Condition对象,该对象可对Lock锁进行获取。这就实现了本方唤醒对方的操作。在这里说明几点:

    1)、对于wait,notify和notifyAll这些方法都是用在同步中,也就是等待唤醒机制,这是因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。

    2)、而这些方法都定义在Object中,是因为这些方法操作同步中的线程时,都必须表示自己所操作的线程的锁,就是说,等待和唤醒的必须是同一把锁。不可对不同锁中的线程进行唤醒。所以这就使得程序是不良的,因此,通过对锁机制的改良,使得程序得到优化。

    3)、等待唤醒机制中,等待的线程处于冻结状态,是被放在线程池中,线程池中的线程已经放弃了执行资格,需要被唤醒后,才有被执行的资格。

    2、对于上面的程序,有两点要说明:

    1)、为何定义while判断标记:

    原因是让被唤醒的线程再判断一次。

    避免未经判断,线程不知是否应该执行,就执行本方的上一个已经执行的语句。如果用if,消费者在等着,两个生成着一起判断完flag后,cpu切换到其中一个如t1,另一个t3在wait,当t1唤醒冻结中的一个,是t3(因为它先被冻结的,就会先被唤醒),所以t3未经判断,又生产了一个。而没消费。

    2)这里使用的是signal方法,而不是signalAll方法。是因为通过Condition的两个对象,分别唤醒对方,这就体现了Lock锁机制的灵活性。可以通过Contidition对象调用Lock接口中的方法,就可以保证多线程间通信的流畅性了。

    二)Thread类中的方法简介:

    在这简单介绍几个Thread中的方法:

    1、停止线程:

    在java 1.5之后,就不再使用stop方法停止线程了。那么该如何停止线程呢?只有一种方法,就是让run方法结束。

    开启多线程运行,运行代码通常为循环结构,只要控制住循环,就可以让run方法结束,也就可以使线程结束。

    注:

    特殊情况:当线程处于冻结状态,就不会读取标记,那么线程就不会结束。如下:

    1. <span style="font-family: Arial; ">class StopThread implements Runnable{  
    2.     private boolean flag = true;  
    3.     public synchronized void run(){  
    4.         while (flag){  
    5.             try{  
    6.                 wait();  
    7.             }catch (InterruptedException e) {  
    8.                 System.out.println(Thread.currentThread().getName() + "----Exception");  
    9.                 flag = false;  
    10.             }  
    11.             System.out.println(Thread.currentThread().getName() + "----run");  
    12.         }  
    13.     }  
    14.     public void changeFlag(){  
    15.         flag = false;  
    16.     }  
    17. }  
    18.   
    19. class  StopThreadDemo{  
    20.     public static void main(String[] args) {  
    21.         StopThread st = new StopThread();  
    22.   
    23.         Thread t1 = new Thread(st);  
    24.         Thread t2 = new Thread(st);  
    25.           
    26.         t1.start();  
    27.         t2.start();  
    28.   
    29.         int n = 0;  
    30.         while (true){  
    31.             if (n++ == 60){  
    32.                 st.changeFlag();  
    33.                 break;  
    34.             }  
    35.             System.out.println("Hello World!");  
    36.         }  
    37.     }  
    38. }</span>  

    这时,当没有指定的方式让冻结的线程回复打破运行状态时,就需要对冻结进行清除。强制让线程回复到运行状态来,这样就可以操作标记让线程结束。

    在Thread类中提供了此种方法:interrupt()。此方法是为了让线程中断,但是并没有结束运行,让线程恢复到运行状态,再判断标记从而停止循环,run方法结束,线程结束。

    1. <span style="font-family: Arial; ">class StopThread implements Runnable{  
    2.     private boolean flag = true;  
    3.     public synchronized void run(){  
    4.         while (flag){  
    5.             try{  
    6.                 wait();  
    7.             }catch (InterruptedException e){  
    8.                 System.out.println(Thread.currentThread().getName() + "----Exception");  
    9.                 flag = false;  
    10.             }  
    11.             System.out.println(Thread.currentThread().getName() + "----run");  
    12.         }  
    13.     }  
    14. }  
    15.   
    16. class  StopThreadDemo{  
    17.     public static void main(String[] args){  
    18.         StopThread st = new StopThread();  
    19.         Thread t1 = new Thread(st);  
    20.         Thread t2 = new Thread(st);       
    21.         t1.start();  
    22.         t2.start();  
    23.         int n = 0;  
    24.         while (true){  
    25.             if (n++ == 60){  
    26.                 t1.interrupt();  
    27.                 t2.interrupt();  
    28.                 break;  
    29.             }  
    30.             System.out.println("Hello World!");  
    31.         }  
    32.     }  
    33. }  
    34. </span>  

    2、守护线程:---setDaemon()

    可将一个线程标记为守护线程,直接调用这个方法。此方法需要在启动前调用守护线程在这个线程结束后,会自动结束,则Jvm虚拟机也结束运行。

    1. <span style="font-family: Arial; ">       ........  
    2.       
    3.     //守护线程(后台线程),在启动前调用。后台线程自动结束  
    4.     t1.setDaemon(true);  
    5.     t2.setDaemon(true);  
    6.     t1.start();  
    7.     t2.start();  
    8.   
    9.       .........</span>  

    3、临时加入线程:--join()

    特点:当A线程执行到B线程方法时,A线程就会等待,B线程都执行完,A才会执行。join可用来临时加入线程执行。

    1. <span style="font-family: Arial; ">class Demo implements Runnable{  
    2.     public void run(){  
    3.         for(int x=0;x<90;x++){  
    4.             System.out.println(Thread.currentThread().getName() + "----run" + x);  
    5.         }  
    6.     }  
    7. }  
    8.   
    9. class  JoinDemo{  
    10.     public static void main(String[] args)throws Exception{  
    11.         Demo d = new Demo();  
    12.         Thread t1 = new Thread(d);  
    13.         Thread t2 = new Thread(d);  
    14.         t1.start();       
    15.         t2.start();  
    16.         t1.join();//等t1执行完了,主线程才从冻结状态恢复,和t2抢执行权。t2执不执行完都无所谓。  
    17.         int n = 0;  
    18.         for(int x=0;x<80;x++){  
    19.             System.out.println(Thread.currentThread().getName() + "----main" + x);  
    20.         }  
    21.         System.out.println("Over");  
    22.     }  
    23. }  
    24. </span>  

    4、优先级:

    setPriority():

    在Thread中,存在着1~10这十个执行级别,最高的是 MAX_PRIORITY 为10,最低是 MIN_PRIORITY 为1,默认优先级是 NORM_PRIORITY 为5;但是并不是优先级越高,就会一直执行这个线程,只是说会优先执行到这个线程,此后还是有其他线程会和此线程抢夺cpu执行权的。

    优先级是可以设定的,可通过setPriority()设定,如:setPriority(Thread.MAX_PRIORITY)设优先级为最大。

    yield():

    此方法可暂停当前线程,而执行其他线程。通过这个方法,可稍微减少线程执行频率,达到线程都有机会平均被执行的效果。如下:

    1. <span style="font-family: Arial; ">class Demo implements Runnable{  
    2.     public void run(){  
    3.         for(int x=0;x<90;x++){  
    4.             System.out.println(Thread.currentThread().toString() + "----run" + x);  
    5.             Thread.yield();//稍微减少线程执行频率。可达到线程都有机会达到平均运行的效果  
    6.         }  
    7.     }  
    8. }  
    9.   
    10. class  YieldDemo{  
    11.     public static void main(String[] args)throws Exception{  
    12.         Demo d = new Demo();  
    13.         Thread t1 = new Thread(d);  
    14.         Thread t2 = new Thread(d);  
    15.         t1.start();  
    16.         t1.setPriority(Thread.MAX_PRIORITY);//设置线程优先级最大       
    17.         t2.start();  
    18.         System.out.println("Over");  
    19.     }  
    20. }</span>  


    对于多线程的知识,还需要慢慢积累,毕竟线程通信可以提高程序运行的效率,这样就可以让程序得到很大的优化。期待新知识······

    展开全文
  • 件与散

    千次阅读 2010-04-11 15:59:00
    我去了湖南衡阳实施一个批发徐福记的客户,这个客户在实施我们软件之前,正在用一款软件开单的,他们在用当前这一款软件开单时,我看到这样的现象,比如说商品名称“徐福记八角芝麻酱馅巧克力 1*6”,规格“1*...

        上个月,我去了湖南衡阳实施一个做批发徐福记的客户,这个客户在实施我们软件之前,正
    用一款软件开单的,他们在用当前这一款软件开单时,我看到这样的现象,比如说商品名称
    是“徐
    福记八角芝麻酱馅巧克力 1*6”,规格是“1*6”的,在打单的时候,他们打销售单写数量
    是写301
    包。我当时就觉得奇怪,为什么不直接写50箱1包,这样对仓库拿货时,不是很清晰
    吗?这个客户
    的开单员说,当前这款软件不支持,还要手工计算一下。
        接下来换成用我们的软件了,我们在显示的件与散的时候,很直观的,比如2件3包、4件、8
    ,但是客户已经习惯了以前的做法,非得要换算成最小单位来,然后再用手工算一下多少件
    多少包
    ,我到现在还是想不通,他们为什么要这样做,难道还要把每一箱打开来算一下有多少
    包吗?有这
    个必要吗?我在湖南邵阳实施徐福记的客户时,当时客户也是要求在打印送货单时
    候,把最小单位
    打出来,为了好给仓库检货,我说没这个必要,直接打印10箱5包、20箱1包给
    仓库检货不是更直观
    吗?如果换成最小单位时,比如10箱5包的,规格是“1*6”,那最小单位
    是:65包,交给仓库检货
    时,他还把65包计算一下出多少件多少包,我觉得完全没有这个必要
    的。看来还是观念在做怪。

    展开全文
  • 1、委托维修:汽修厂前台接车,客户的车进厂后进行一定的评估,需要修理那些项目,需要什么配件,及修理以外的代办业务,以及客户所委托的相关修理业务,打印委托维修让客户确认。 2、派工:开了委托接后,...
  • 《知乎网页助手》让知乎体验更顺滑,工具本身解决的用户痛点,知乎官方可以,但为了平台利益,而不会去的。 087《豆瓣资源下载大师》1秒搞定豆瓣电影|音乐|图书下载 《豆瓣资源下载大师》一款好用的搜索...
  • 智点门窗工厂软件

    2018-11-12 14:32:27
    智点木门软件专门为木门工厂开发的生产管理软件,集订单、生产、销售、货运、账务、工人计件工资等于一体,包含套线自动计算,洞口净尺寸计算,生产打印,包装标签打印,扫码计件,计件工资计算,移动下单,...
  • 比如你面试后端工程师,面试官问你的缺点是什么的话,你可以这样说:自己比较内向,平时不太爱与人交流,但是考虑到以后可能要和客户沟通,自己正在努力改。 面试官问期望薪资时,应该如何回答? 曾经在面试之前我...
  • 二十三种设计模式【PDF版】

    热门讨论 2011-05-30 14:13:49
    如果你还不了解设计模式是什么的话? 那就先看设计模式引言 ! 学习 GoF 设计模式的重要性 建筑和软件中模式之异同 A. 创建模式 设计模式之 Singleton(单态/单件) 阎宏博士讲解:单例(Singleton)模式 保证...
  • 拿到一台新的Windows电脑,我会做什么? 线上排查工具Arthas 你会换掉Postman吗?我正在用HTTP Client... curl 使用 为什么需要Docker? Docker入门为什么可以这么简单? 聊聊Docker镜像 Java精美思维导图 程序员...
  • 3.增加ETTask,ETTask一个轻量级线程的task,相比Task性能更强,GC更少 4.增加了ETBook,写了一些入门的文章给大家学习 5.升级了ILRuntime,Hotfix.dll目前完全支持Unity编译,并且mac上也能编译 6.增加了状态...
  • 具体微观代码级: 这一级具体到每一行代码的实现,到了用代码指令级的地步,这段代码是什么意思?为什么要这么设计?有没有更好的方案? 鸿蒙内核源码注解分析 试图从细微处去解释代码实现层,英文真的天生适合设计成...
  • Oracle专家高级编程--详细书签版

    热门讨论 2012-08-21 11:57:09
    我直接与客户交道,描述并构建他们的系统,更频繁的帮助他们重建或优化数据库(“优化”经常“重建”的同义词).此外,我Oracle杂志的“AskTom”栏目背后的Tom,回答用户有关Oracle数据库和工具的问题.通常在一...
  • 大话数据结构

    2018-12-14 16:02:18
    因为美国的黑夜就是中国的白天,利用互联网,他的员工白天上班就可以监控到美国仓库夜间的实际情况,如果发生了像火灾、偷盗这样的突发事件,及时电话到美国当地相关人员处理 7.4.1邻接矩阵 224 7.4.2邻接表 228 ...
  • 一文带你搞懂API网关

    2020-12-28 06:45:32
    比如针对台网关、还是整个网关集群,如果整个集群的话,需要考虑到网关缩容、扩容时修改对应的限流数。 - 分布式。分布式的就需要一个存储节点维护当前接口的调用数,比如redis、sentinel等...
  • 有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以改进成小工具。 Java右键弹出...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
    有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以改进成小工具。 Java右键弹出...
  • 业务角度出发,如果是单条多频次bean对象插入明显Sqlite占优,ObjectBox执行速度有所下降,这种场景下可以考虑队列的方式批量插入; 经过测试,在查询速度方面有以下建议: 主键ID查询条数据在百万级数据中...
  • 大家在实际项目上还是要尽量少造轮子,有优秀的框架之后尽量就去用,Dubbo 在各个方面的都比较好和完善。 如果我要自己写的话,需要提前了解哪些知识 Java : 动态代理机制; 序列化机制以及各种序列化框架的...
  • 1、为什么要引入“进程” (1)进程调度属于低级处理机管理,即确定系统中哪个进程将获得CPU;而作业调度属于高级处理机管理,即确定系统中哪些作业将获得CPU。 (2)进程一个具有一定独立功能的程序...
  •   Canvas可操作的层面像素级别的,你觉得还有什么不到吗? 介绍(Introduce)   本教程一套详细介绍Canvas的系列学习教程同时也查阅工具,以实例为主,采用由泛到精的学习结构,所有的小节都有单独的...
  • 创建此工程为了巩固基础知识 当然能对社区点贡献也我小小的心愿~ 本工程包含了 SpringAOP,死锁,JUC同步锁,读-写同步锁,ThreadLocal使用,JUC线程池和Spring提供的线程池,jdk 1.8 中的日期时间API,数据结构...
  • 我在train.py文件中加入了fp16与gradient accumulation支持,如果你安装了apex并且知道fp16是什么的话,可以修改变量fp16=True来启用。但是目前fp16可能不收敛,原因不明。 联系作者 Mail:ned1991@gmail.com ...
  • 8.2 什么是优化 338 8.3 查询优化器如何研究查询计划 339 8.3.1 规则 339 8.3.2 属性 339 8.3.3 替代项的存储——“备注” 341 8.3.4 运算符 341 8.4 优化器架构 346 8.4.1 优化之前 347 8.4.2 ...

空空如也

空空如也

1 2 3
收藏数 44
精华内容 17
关键字:

仓库打单是做什么的