00:00
各位同学早上好啊,今天我们来谈第五道面试题,谈一下string buffer和string build两者的区别,那这一块呢,一般在开发中,因为有性能和安全的角度,我们应该怎么做选择呢?来一起听一下。则呢,OK,好,下面跟着我来看一眼啊,那大家可以看到呢,此刻你看到这一块东西啊,这个是历史遗留产物啊,因为最早的话呢,我们还有人会问到像这个字符串跟他们的区别,所以呢,这边顺带的说一下,因为字符串的话呢,每次做拼接都会产生新的对象,而string buffer和string build的话呢,每次拼接呢都不会产新的对象,所以呢,如果我们当我们需要在程序里面去做字符串拼接这个动作,那一般来说,我们推荐采用视string buffer或视频build的啊,绝对不会去用字符串的方式。好,那下面的话,我们来看一下这两者啊,有什么区别呢?很简单啊,我们来给大家演示一下,来看代码。好,这个代码的话呢,已经转的应该是比较大了啊,应该大家都在在屏幕上能看的比较清晰,我们来看一下使用buffer啊,然后这里面的话呢,我们比如说可以这样来写一下啊,使用buffer,然后等于这个new string buffer,诶不对啊,来看一眼这个new string buffer,好这边的话呢,我们可以敲一个A,然后呢,假如说这是初始化的一个变量之之后的话呢,我可以在这里面的话,通过a pen的这么一个方法去给它做一些拼接相的操作,对不对,好好这样就行了啊,好,这是一种方式,同理呢,我们来看一下string build啊build的话我们会看到呢,其实也类似用法,你会发现几乎是一模一样的,好,比如说我也写个A。
01:33
好,然后的话呢,接下来我们也做一个拼接的一个操作。呃,使用标的啊。然后A你看也是一个样啊,也是一个样,好没有问题,大家可以看到这两段程序的话呢,几乎来说是一模一样对吧?好,但是的话呢,他们俩呢,有什么区别呢?本质的区别在于什么呢?在于这里我们来进来看一下源码,来点过来。好,我们可以再放大一下。好,大家可以看到呢,在string buffer这个类里面,它的源码这一块里面,它加了一个什么关键词啊,加了一个synchize关键词,这个是一个同步锁的关键词,对不对,意味着什么呢?意味着这个方法有它照着啊这个地方属于线程安全的一个操作。
02:14
好,那么我们再回头来看一下这一块,这一块我们来看它有没有被它照着呢,来看一下,点过来好放大。你看这一块,你看很明显它没有那个刚刚那个关键词,没有刚刚这个size啊,这关键词来做来来修饰它,所以呢,这个方法呢,在多线程的情况下,它并不是线程安全的。好,所以呢,很简单,我们可以得到一个结论啊,来看一眼,这个结论就是什么呢?就是前指啊。是现在安全的就是这个STEM buffer,因为它内部的话呢,它的很多方法都用了这个关键词来修饰,而这个string builder的话呢,刚我们看到看到啊,它的方法是没有修饰的,所以从角度来说的话呢,这一块啊,它是线程安全的,而这个类呢,是线程不安全的。好,那我们知道啊,所谓的线程安全,所谓的上锁,诶就好比我们这个进个门一样,是吧,你想啊,你没有锁,你是不是进去很快,但是有把锁的话,你得开锁,这个动作本身就比较慢啊,当然我们这个形象的说法啊,所以的话呢,很显然就是这个线程不安全的东西呢,它性能更高。
03:16
啊,性能更高啊,OK,所以在开发中优先选择它,但是这边我要问一个问题啊,我经常在面试中的话呢,以前啊,就是比如说我们最开始面一些初级岗位同学的同学的时候呢,我们会问到一个非常简单的问题,就是比如说问这两个东西的区别,那么通常来说注意啊,通常来说这个地方敲重点了啊。同学们都会答到这个问题,就是说都答对啊,都答说这个东西是安全的啊,这个东西是不安全的对吧?然后问他怎么选择,这个时候他就会跟我说怎么选择呢?他说如果我们考虑性能的话,推荐选它。如果我们考虑这个安全的话,我们选它,那我说什么时候我们就是,那我说我们如果选选择的这个性能是不是可以不考虑安全啊,他说这个东西啊,只能是选择啊鱼额性能不可兼得嘛,所以如果为了性能的话,我们一定的这个现在安全问题也可以是也是可以接受的啊OK,好,那你认为这样可以接受吗?就是我们为了性能,然后不不考虑这个安全问题。
04:14
OK,能不能接受?那么你可以在这里思考一下啊,你的答案是什么啊?能不能接受啊,就是只要性能,不要安全。答案是不行的啊,因为我们要考虑实际的情况,就说什么呢,在什么时候我们可以考虑用它呢?但是依然是安全的呢,很简单,同学们看一眼啊,来,看一眼,回到我们的代码里面来。此刻啊,你看,假如说我是在一个方法里面,每次我用它的时候都要拗一个新的对象出来,在方法里面每次都要扭一次,意味着什么呢?意味着这个方案每次被调一次的时候,它都会被new一次的一个对象出来,那这样的话,是不是意味着这个时候每一个请求,每一个线程都会单独有一份string build的对象,那就不会存在多个线程去共享它的问题?那么这个东西虽然本身的内部是没有加速的,但是没有问题啊,因为一个线程有一份读一份就没问题了,对不对,但是如果说我们是什么,我们是做一个全局变量写外面的。
05:11
啊,一个全局变量写在外面的,然后在内部去共享的这么一个东西,诶你这个时候再用10BUILD的,这就不妥了,为什么呢?因为大家可以看到啊,这个时候的话呢,假设啊,你看这个时候的话呢,我们在内部啊,这边经常蛋白注失掉。如果说是这样。那这个时候的话呢,我们在这里面A点,我们说成叫static啊对OK,你看到在这里头的话呢,如果说是这样子的话啊,我们这个时候有多个线程,假如说有一个线程A啊,线程A。写一下啊。现在A的话呢,就掉了这个方法啊,调了这个方法,那这个方法里面的话就会触发这个东西的执行,对吧?然后呢,线程B也来了,他也调了这个方法,那要道里的话呢,它也会去掉到这个地方,而由于这个地方呢没有上锁,所以的话这个地方就会出现问题是吧?就有可能出现问题对吧?有可能啊好,所以这样的话就有问题了,所以当你如果说这个东西想作为全局变量的话,那这个时候的话,我们就应该换成什么呢?应该换成四菌buffer啊才是OK的。
06:12
啊,OK,好,所以如果说我们只是在内部里面,在方法内部,我们每次都new一次的话,那你大胆大胆放心的用40BUILD的,因为每一次每来一次请求,每来一个线程都会重新六一份,所以就不存在多个线程共享这么一个东西的问题,所以它就不会发生现场安全的问题,对吧?好,这就是关于这两些东西,东西怎么选择,所以我们是什么?我们是既要考虑安全,又要考虑性能啊,而不是说两害其轻取其一,对吧?OK,是要在综合想权择下都要的一个情况下的考虑啊,如果说我们这个时候呢,不能用,就现在安全是一个重要的问题,不能忽视,不能忽视它啊,不能忽视它好,所以这最终的答案就是这么回事了啊,就是在我们能够安全使用它的时候,优先使用一个没上锁的东西,保证执行性能更高效。
07:03
好了啊,今天的话呢,关于这道题我们就聊到这啊,希望大家能够对大家有所帮助,如果感觉对你有帮助的话呢,欢迎大家点个赞,下节课我们继续。
我来说两句