请问在有关手机维修的资料里,qualifier作用代表什么意思

前段时间跟着老大去面试,几乎每个面试者都被问了类型判断的问题,有些能答出来怎么判断js内的各个类型,还能列举几种方法去判断,但是问到这些方法有什么区别的时候,却答不出来;有些连判断的方法都说不出。我在一边看着都着急呀...&/p&&p&
趁着这个机会,我也简单复习整理一下javascript中的类型判断的方法;本文会列举js中判断类型的各种方法,然后窥探一下它们的原理。希望看完能对准备去面试的小伙伴们一点启发,至少面试的时候能“蒙混过关”。&/p&&p&
要想判断js中的数据类型,首先要知道js中有几种数据类型:&/p&&ul&&li&null(空)&/li&&li&undefined(未声明)&/li&&li&number(数字)&/li&&li&string(字符串)&/li&&li&object(对象)&/li&&li&boolean(布尔值)&/li&&li&symbol(符号,es6新增)&/li&&/ul&&blockquote&
js中只有这7种数据类型,其他的都是对象的子类型(居然有几个面试者说数组也是js的数据类型,晕)&/blockquote&&p&
知道了js中有几种数据类型,接下来就是判断各种类型了,先来看看最简单又最常用的方法&/p&&h2&typeof&/h2&&p&
typeof运算符后可跟着一个操作数,用于判断该操作数的数据类型;&b&typeof适用于上面7种数据类型中除null、object的其他5种类型的判断&/b&:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&typeof&/span& &span class=&kc&&undefined&/span&&span class=&p&&;&/span&
&span class=&c1&&// &undefined&;&/span&
&span class=&k&&typeof&/span& &span class=&mi&&1&/span&&span class=&p&&;&/span&
&span class=&c1&&// &number&;&/span&
&span class=&k&&typeof&/span& &span class=&s1&&'1'&/span&&span class=&p&&;&/span&
&span class=&c1&&// &string&;&/span&
&span class=&k&&typeof&/span& &span class=&kc&&true&/span&&span class=&p&&;&/span&
&span class=&c1&&// &boolean&;&/span&
&span class=&k&&typeof&/span& &span class=&nx&&Symbol&/span&&span class=&p&&();&/span&
&span class=&c1&&// &symbol&;&/span&
&span class=&k&&typeof&/span& &span class=&p&&{&/span&&span class=&nx&&a&/span& &span class=&o&&:&/span& &span class=&mi&&1&/span&&span class=&p&&};&/span&
&span class=&c1&&// &object&;&/span&
&/code&&/pre&&/div&&p&以上都是可靠正确而且易于理解的,接下来我们一起看几个正确的,但似乎不是我们期望的结果的例子:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&typeof&/span& &span class=&kc&&null&/span& &span class=&o&&===&/span& &span class=&s2&&&object&&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&k&&typeof&/span& &span class=&kd&&function&/span& &span class=&p&&()&/span& &span class=&p&&{}&/span& &span class=&o&&===&/span& &span class=&s2&&&function&&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&/code&&/pre&&/div&&p&我们先说第一个,这就牵扯到typeof的原理:&/p&&blockquote&
在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null的类型标签也成为了 0,typeof null就错误的返回了&object&。&/blockquote&&p&
上面这段话引用自&a href=&http://link.zhihu.com/?target=https%3A//developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/typeof& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&MDN&/a&,这说明了typeof在判断js数据类型的时候是根据js的“&i&类型标签&/i&”来进行的。&/p&&p&
实际上(typeof的其中一种实现),js底层储存变量时会在变量的机器码低位1-3位储存变量类型信息的。这几位机器码就是上文说到的“类型标签“;下面列举下几个类型的”类型标签“:&/p&&ul&&li&000: 对象&/li&&li&010: 浮点数&/li&&li&100: 字符串&/li&&li&110: 布尔值&/li&&li&1: 整数&/li&&/ul&&p&
由于null的机器码全是0(1-3位自然都是0),恰好符合了对象的“类型标签”,因此&typeof null === 'object'&返回的是true(是个公认的‘bug’,但应该现在和未来都不会修复了)。那么这是不是表示typeof不能用来判断null呢?当然不是啦:&b&我们知道object是个真值,而null是“假的”&/b&&i&(注意:使用new运算符创建的对象都是真值,即使是'new Boolean(false)')&/i&,所以我们可以这样判断&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&var&/span& &span class=&nx&&a&/span& &span class=&o&&=&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&o&&!&/span&&span class=&nx&&a&/span& &span class=&o&&&&&/span& &span class=&k&&typeof&/span& &span class=&nx&&a&/span& &span class=&o&&===&/span& &span class=&s1&&'object'&/span& &span class=&c1&&// true&/span&
&/code&&/pre&&/div&&p&
再来看第二个,我们知道,函数是对象的子类型,按道理来说&typeof function () {} === 'object'&才对,但是结果却是&function&。这是因为,&b&函数是一个“特殊的对象”,它特殊就特殊在它内部有一个属性[[call]],这个属性使它变成一个“可调用的对象”。&/b&而根据规范,实现了[[call]]属性的对象,typeof的结果是“function”;附上规范:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-6cdf7e3af49c6fc7d4b0371_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&868& data-rawheight=&413& class=&origin_image zh-lightbox-thumb& width=&868& data-original=&https://pic2.zhimg.com/v2-6cdf7e3af49c6fc7d4b0371_r.jpg&&&/figure&&p&
函数真的是一个很神奇的对象。就算是用new创建出来的函数对象,也拥有call属性。所以,它依然“很倔强地“返回“function”&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&k&&typeof&/span& &span class=&k&&new&/span& &span class=&nb&&Number&/span&&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&)&/span& &span class=&o&&===&/span& &span class=&s1&&'object'&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&k&&typeof&/span& &span class=&k&&new&/span& &span class=&nb&&String&/span&&span class=&p&&(&/span&&span class=&s2&&&a&&/span&&span class=&p&&)&/span& &span class=&o&&===&/span& &span class=&s1&&'object'&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&...&/span&
&span class=&k&&typeof&/span& &span class=&k&&new&/span& &span class=&nb&&Function&/span&&span class=&p&&(&/span&&span class=&s2&&&console.log(123);&&/span&&span class=&p&&)&/span& &span class=&o&&===&/span& &span class=&s1&&'function'&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&/code&&/pre&&/div&&h2&instanceof&/h2&&p&
typeof能判断一个数据是不是对象,却不能判断它是对象的哪个“子类型”,比如说不能判断是否为数组,是否为日期等。这个时候就可以用instanceof来进行判断了。但是,&i&instanceof只能判断是否是你预期的类型且只能用于对象子类型的判断&/i&。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&p&&[&/span&&span class=&mi&&1&/span&&span class=&p&&,&/span& &span class=&mi&&2&/span&&span class=&p&&]&/span& &span class=&k&&instanceof&/span& &span class=&nb&&Array&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&kd&&function&/span& &span class=&nx&&foo&/span&&span class=&p&&()&/span& &span class=&p&&{})&/span& &span class=&k&&instanceof&/span& &span class=&nb&&Function&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&(&/span&&span class=&mi&&2018&/span&&span class=&p&&))&/span& &span class=&k&&instanceof&/span& &span class=&nb&&Date&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Number&/span&&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&))&/span& &span class=&k&&instanceof&/span& &span class=&nb&&Number&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&)&/span& &span class=&k&&instanceof&/span& &span class=&nb&&Number&/span&&span class=&p&&;&/span& &span class=&c1&&// false&/span&
&/code&&/pre&&/div&&blockquote&
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。&/blockquote&&p&
a instanceof b,instanceof会去查找a的原型链(这里不展开讨论)上是否有b的prototype属性;如果有,就返回true,否则返回false。即判断a的原型链上是否有&b&a._proto__ === b.prototype&/b&返回true。instanceof根据规范的实现如下:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-0fffb54cfeee926f9525_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&548& data-rawheight=&203& class=&origin_image zh-lightbox-thumb& width=&548& data-original=&https://pic2.zhimg.com/v2-0fffb54cfeee926f9525_r.jpg&&&/figure&&p&&br&&/p&&p&
关于instanceof用于继承等其他方面的介绍,这里推荐一篇&a href=&http://link.zhihu.com/?target=https%3A//www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&文章&/a&,讲得非常详细,且通俗易懂。&/p&&h2&constructor&/h2&&p&
对于对象子类型的判断方法,除了用instanceof运算符来判断,还可以利用&i&对象的constructor属性&/i&来进行判断。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&p&&({&/span&&span class=&nx&&a&/span&&span class=&o&&:&/span&&span class=&mi&&1&/span&&span class=&p&&}).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&Object&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&([&/span&&span class=&mi&&1&/span&&span class=&p&&,&/span&&span class=&mi&&2&/span&&span class=&p&&]).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&Array&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&k&&new&/span& &span class=&nb&&Date&/span&&span class=&p&&(&/span&&span class=&mi&&2018&/span&&span class=&p&&)).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&Date&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&kd&&function&/span& &span class=&nx&&foo&/span&&span class=&p&&()&/span& &span class=&p&&{}).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&Function&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&s1&&'1'&/span&&span class=&p&&).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&String&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&Number&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&span class=&p&&(&/span&&span class=&kc&&true&/span&&span class=&p&&).&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nb&&Boolean&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&/code&&/pre&&/div&&p&
从上面代码我们可以看出,constructor属性不仅仅可以用于对象“子类型的判断”,还可以用于基本类型的判断。那么constructor是什么?它又是怎么实现类型的判断的呢?&/p&&p&
constructor首先是一个属性,它&b&返回创建实例对象的Object构造函数的引用&/b&。对于原始数据类型来说,constructor属性是只读的。&/p&&p&
我们先来看全等号左右两边分别在浏览器会打印出什么&/p&&figure&&img src=&https://pic2.zhimg.com/v2-1e96536e1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&232& data-rawheight=&80& class=&content_image& width=&232&&&/figure&&p&
这说明&b&constructor的值是对构造函数本身的引用,而不是函数名的字符串&/b&。也就是说&b&constructor属性返回的是对象的构造函数,基本类型指向对应的内置对象的构造函数&/b&,如:Number、String、Date、Array等。注意,&b&null和undefined没有构造函数。&/b&由于constructor是一个属性,所以一般情况下他的值是可以被任意修改&/p&&figure&&img src=&https://pic2.zhimg.com/v2-7cd68ff1f15_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&523& data-rawheight=&106& class=&origin_image zh-lightbox-thumb& width=&523& data-original=&https://pic2.zhimg.com/v2-7cd68ff1f15_r.jpg&&&/figure&&p&
这里提到一个概念:构造函数。我们可以简单地认为,只要能用new运算符调用的函数,就可以作为构造函数。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&function&/span& &span class=&nx&&Person&/span& &span class=&p&&(&/span&&span class=&nx&&name&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&name&/span& &span class=&o&&=&/span& &span class=&nx&&name&/span&&span class=&p&&;&/span&
&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&sayHi&/span& &span class=&o&&=&/span& &span class=&kd&&function&/span& &span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&s1&&'Hi,'&/span& &span class=&o&&+&/span& &span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&name&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&kd&&var&/span& &span class=&nx&&man&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&nx&&Person&/span&&span class=&p&&(&/span&&span class=&s1&&'pxp'&/span&&span class=&p&&);&/span&
&span class=&nx&&man&/span&&span class=&p&&.&/span&&span class=&nx&&sayHi&/span&&span class=&p&&();&/span& &span class=&c1&&// Hi,pxp&/span&
&/code&&/pre&&/div&&p&
当Person没有用new运算符调用时,它是一个普通的函数(this会指向window);当他用new运算符调用时,他就是一个构造函数;&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nx&&man&/span&&span class=&p&&.&/span&&span class=&nx&&constructor&/span& &span class=&o&&===&/span& &span class=&nx&&Person&/span&&span class=&p&&;&/span& &span class=&c1&&// true&/span&
&/code&&/pre&&/div&&p&
因此,constructor虽然可以判断大部分的类型,但是&b&无法判断null和undefined&/b&;而且由于它可以被修改,所以&i&用constructor来判断数据的类型其实是不稳定且有些不可靠&/i&的。&/p&&h2&prototype&/h2&&p&
上面介绍的几种方法不是不能判断对象就只能判断对象,那么有没有方法是通用的呢?答案是有的:利用“Object.prototype.toString.call('...')”来进行判断。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&nb&&Object&/span&&span class=&p&&.&/span&&span class=&nx&&prototype&/span&&span class=&p&&.&/span&&span class=&nx&&toString&/span&&span class=&p&&.&/span&&span class=&nx&&call&/span&&span class=&p&&(&/span&&span class=&s1&&'1'&/span&&span class=&p&&);&/span& &span class=&c1&&// &[object String]&&/span&
&span class=&nb&&Object&/span&&span class=&p&&.&/span&&span class=&nx&&prototype&/span&&span class=&p&&.&/span&&span class=&nx&&toString&/span&&span class=&p&&.&/span&&span class=&nx&&call&/span&&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&);&/span& &span class=&c1&&// &[object Number]&&/span&
&span class=&nb&&Object&/span&&span class=&p&&.&/span&&span class=&nx&&prototype&/span&&span class=&p&&.&/span&&span class=&nx&&toString&/span&&span class=&p&&.&/span&&span class=&nx&&call&/span&&span class=&p&&(&/span&&span class=&kc&&true&/span&&span class=&p&&);&/span& &span class=&c1&&// &[object Boolean]&&/span&
&span class=&nb&&Object&/span&&span class=&p&&.&/span&&span class=&nx&&prototype&/span&&span class=&p&&.&/span&&span class=&nx&&toString&/span&&span class=&p&&.&/span&&span class=&nx&&call&/span&&span class=&p&&([&/span&&span class=&mi&&1&/span&&span class=&p&&,&/span& &span class=&mi&&2&/span&&span class=&p&&,&/span& &span class=&mi&&3&/span&&span class=&p&&]);&/span& &span class=&c1&&// &[object Array]&&/span&
&span class=&nb&&Object&/span&&span class=&p&&.&/span&&span class=&nx&&prototype&/span&&span class=&p&&.&/span&&span class=&nx&&toString&/span&&span class=&p&&.&/span&&span class=&nx&&call&/span&&span class=&p&&(&/span&&span class=&kd&&function&/span& &span class=&nx&&foo&/span&&span class=&p&&()&/span& &span class=&p&&{});&/span& &span class=&c1&&// &[object Function]&&/span&
&/code&&/pre&&/div&&p&
Object.prototype属性表示Object的原型对象;toString()方法返回一个表示该对象的字符串;call用于指定this。所以使用Object.prototype.toString.call(date)会&b&返回一个表示date的原型对象的字符串&/b&(如果date不是对象,会先转化为对象,null和undefined除外),附上规范:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-5a1c72feaf5bda541f2b4aed42df4a88_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&882& data-rawheight=&215& class=&origin_image zh-lightbox-thumb& width=&882& data-original=&https://pic1.zhimg.com/v2-5a1c72feaf5bda541f2b4aed42df4a88_r.jpg&&&/figure&&p&可以看出,Object.prototype.toString会执行下面的步骤:&/p&&ol&&li&如果this的值是undefined, 返回 &[object Undefined]&&/li&&li&如果this的值是null, 返回 &[object Null]&&/li&&li&令 O 为以 this 作为参数调用 ToObject 的结果(转化为对象)&/li&&li&令 class 为 O 的 [[Class]] 内部属性的值&/li&&li&返回三个字符串 &[object &, class, and &]& 连起来的字符串&/li&&/ol&&p&
由于Object.prototype.toString.call(...)会返回“[object Type]”的字符串,所以通常会封装成一个函数进行调用,下面举例判断数组,其他同理。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kd&&function&/span& &span class=&nx&&isArray&/span& &span class=&p&&(&/span&&span class=&nx&&obj&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nb&&Object&/span&&span class=&p&&.&/span&&span class=&nx&&prototype&/span&&span class=&p&&.&/span&&span class=&nx&&toString&/span&&span class=&p&&.&/span&&span class=&nx&&call&/span&&span class=&p&&(&/span&&span class=&nx&&obj&/span&&span class=&p&&)&/span& &span class=&o&&===&/span& &span class=&s1&&'[object Array]'&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&nx&&isArray&/span&&span class=&p&&([&/span&&span class=&mi&&1&/span&&span class=&p&&,&/span& &span class=&mi&&2&/span&&span class=&p&&,&/span& &span class=&mi&&3&/span&&span class=&p&&]);&/span& &span class=&c1&&// true&/span&
&span class=&nx&&isArray&/span&&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&);&/span& &span class=&c1&&// false&/span&
&/code&&/pre&&/div&&p&
Object.prototype.toString虽然通用性强,但是相对来说比较繁琐,一般需要封装成函数进行调用才能进行判断,所以在日常工作中应结合上面几种判断类型的方法,选择最简单且可靠的。&/p&&p&
综上所述,当你想判断一个基本类型的数据时,你可以用typeof去判断,它很简单,而且可靠;当你想判断一个对象属于哪个子类型时,你可以使用instanceof运算符或constructor属性,但是你需要有个预期的类型,不然就要针对每一种类型写不一样的if...else...语句,还有一点需要注意的就是constructor属性可以被修改,所以并不可靠;如果你不嫌代码量多,要求准确且全面,那你可以用Object.prototype.toString.call()进行判断。
前段时间跟着老大去面试,几乎每个面试者都被问了类型判断的问题,有些能答出来怎么判断js内的各个类型,还能列举几种方法去判断,但是问到这些方法有什么区别的时候,却答不出来;有些连判断的方法都说不出。我在一边看着都着急呀... 趁着这个机会,我也简…
&p&&b&前言&/b&&/p&&p&个人认为,学习,内容越多、越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的。这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题。&br&这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些问题网上有、可能有些问题对应的答案也有、也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不吝指教。&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-a3e3b16dadb0ff8e217527a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&651& data-rawheight=&463& class=&origin_image zh-lightbox-thumb& width=&651& data-original=&https://pic2.zhimg.com/v2-a3e3b16dadb0ff8e217527a_r.jpg&&&/figure&&p&&b&40个问题汇总&/b&&/p&&p&&b&1、多线程有什么用?&/b&&/p&&p&一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓”知其然知其所以然”,”会用”只是”知其然”,”为什么用”才是”知其所以然”,只有达到”知其然知其所以然”的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法:&br&(1)发挥多核CPU的优势&br&随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的”多线程”那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程”同时”运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。&br&(2)防止阻塞&br&从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。&br&(3)便于建模&br&这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务,任务B、任务C、任务D,分别建立程序模型,并通过多线程分别运行这几个任务,那就简单很多了。&/p&&p&&b&2、创建线程的方式&/b&&/p&&p&比较常见的一个问题了,一般就是两种:&br&(1)继承Thread类&br&(2)实现Runnable接口&br&至于哪个好,不用说肯定是后者好,因为实现接口的方式比继承类的方式更灵活,也能减少程序之间的耦合度,面向接口编程也是设计模式6大原则的核心。&/p&&p&&b&3、start()方法和run()方法的区别&/b&&/p&&p&只有调用了start()方法,才会表现出多线程的特性,不同线程的run()方法里面的代码交替执行。如果只是调用run()方法,那么代码还是同步执行的,必须等待一个线程的run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其run()方法里面的代码。&/p&&p&&b&4、Runnable接口和Callable接口的区别&/b&&/p&&p&有点深的问题了,也看出一个Java学习知识的广度。&br&Runnable接口中的run()方法的返回值是void,它做的事情只是纯粹地去执行run()方法中的代码而已;Callable接口中的call()方法是有返回值的,是一个泛型,和Future、FutureTask配合可以用来获取异步执行的结果。&br&这其实是很有用的一个特性,因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性,某条线程是否执行了?某条线程执行了多久?某条线程执行的时候我们期望的数据是否已经赋值完毕?无法得知,我们能做的只是等待这条多线程的任务执行完毕而已。而Callable+Future/FutureTask却可以获取多线程运行的结果,可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务,真的是非常有用。&/p&&p&&b&5、CyclicBarrier和CountDownLatch的区别&/b&&/p&&p&两个看上去有点像的类,都在java.util.concurrent下,都可以用来表示代码运行到某个点上,二者的区别在于:&br&(1)CyclicBarrier的某个线程运行到某个点上之后,该线程即停止运行,直到所有的线程都到达了这个点,所有线程才重新运行;CountDownLatch则不是,某线程运行到某个点上之后,只是给某个数值-1而已,该线程继续运行&br&(2)CyclicBarrier只能唤起一个任务,CountDownLatch可以唤起多个任务&br&(3)CyclicBarrier可重用,CountDownLatch不可重用,计数值为0该CountDownLatch就不可再用了&/p&&p&&b&6、Volatile关键字的作用&/b&&/p&&p&一个非常重要的问题,是每个学习、应用多线程的Java程序员都必须掌握的。理解volatile关键字的作用的前提是要理解Java内存模型,这里就不讲Java内存模型了,可以参见第31点,volatile关键字的作用主要有两个:&br&(1)多线程主要围绕可见性和原子性两个特性而展开,使用volatile关键字修饰的变量,保证了其在多线程之间的可见性,即每次读取到volatile变量,一定是最新的数据&br&(2)代码底层执行不像我们看到的高级语言—-Java程序这么简单,它的执行是Java代码–&字节码–&根据字节码执行对应的C/C++代码–&C/C++代码被编译成汇编语言–&和硬件电路交互,现实中,为了获取更好的性能JVM可能会对指令进行重排序,多线程下可能会出现一些意想不到的问题。使用volatile则会对禁止语义重排序,当然这也一定程度上降低了代码执行效率&br&从实践角度而言,volatile的一个重要作用就是和CAS结合,保证了原子性,详细的可以参见java.util.concurrent.atomic包下的类,比如AtomicInteger。&/p&&p&&b&7、什么是线程安全&/b&&/p&&p&又是一个理论的问题,各式各样的答案有很多,我给出一个个人认为解释地最好的:如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果,那么你的代码就是线程安全的。&br&这个问题有值得一提的地方,就是线程安全也是有几个级别的:&br&(1)不可变&br&像String、Integer、Long这些,都是final类型的类,任何一个线程都改变不了它们的值,要改变除非新创建一个,因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用&br&(2)绝对线程安全&br&不管运行时环境如何,调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价,Java中标注自己是线程安全的类,实际上绝大多数都不是线程安全的,不过绝对线程安全的类,Java中也有,比方说CopyOnWriteArrayList、CopyOnWriteArraySet&br&(3)相对线程安全&br&相对线程安全也就是我们通常意义上所说的线程安全,像Vector这种,add、remove方法都是原子操作,不会被打断,但也仅限于此,如果有个线程在遍历某个Vector、有个线程同时在add这个Vector,99%的情况下都会出现ConcurrentModificationException,也就是fail-fast机制。&br&(4)线程非安全&br&这个就没什么好说的了,ArrayList、LinkedList、HashMap等都是线程非安全的类&/p&&p&&b&8、Java中如何获取到线程dump文件&/b&&/p&&p&死循环、死锁、阻塞、页面打开慢等问题,打线程dump是最好的解决问题的途径。所谓线程dump也就是线程堆栈,获取到线程堆栈有两步:&br&(1)获取到线程的pid,可以通过使用jps命令,在Linux环境下还可以使用ps -ef | grep java&br&(2)打印线程堆栈,可以通过使用jstack pid命令,在Linux环境下还可以使用kill -3 pid&br&另外提一点,Thread类提供了一个getStackTrace()方法也可以用于获取线程堆栈。这是一个实例方法,因此此方法是和具体线程实例绑定的,每次获取获取到的是具体某个线程当前运行的堆栈,&/p&&p&&b&9、一个线程如果出现了运行时异常会怎么样&/b&&/p&&p&如果这个异常没有被捕获的话,这个线程就停止执行了。另外重要的一点是:如果这个线程持有某个某个对象的监视器,那么这个对象监视器会被立即释放&/p&&p&&b&10、如何在两个线程之间共享数据&/b&&/p&&p&通过在线程之间共享对象就可以了,然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待,比方说阻塞队列BlockingQueue就是为线程之间共享数据而设计的。&/p&&p&&b&11、sleep方法和wait方法有什么区别&/b&&/p&&p&这个问题常问,sleep方法和wait方法都可以用来放弃CPU一定的时间,不同点在于如果线程持有某个对象的监视器,sleep方法不会放弃这个对象的监视器,wait方法会放弃这个对象的监视器&/p&&p&&b&12、生产者消费者模型的作用是什么&/b&&/p&&p&这个问题很理论,但是很重要:&br&(1)通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生产者消费者模型最重要的作用&br&(2)解耦,这是生产者消费者模型附带的作用,解耦意味着生产者和消费者之间的联系少,联系越少越可以独自发展而不需要收到相互的制约&/p&&p&&b&13、ThreadLocal有什么用&/b&&br&简单说ThreadLocal就是一种以空间换时间的做法,在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap,把数据进行隔离,数据不共享,自然就没有线程安全方面的问题了&/p&&p&&b&14、为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用&/b&&/p&&p&这是JDK强制的,wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁&/p&&p&&b&15、wait()方法和notify()/notifyAll()方法在放弃对象监视器时有什么区别&/b&&/p&&p&wait()方法和notify()/notifyAll()方法在放弃对象监视器的时候的区别在于:wait()方法立即释放对象监视器,notify()/notifyAll()方法则会等待线程剩余代码执行完毕才会放弃对象监视器。&/p&&p&&b&16、为什么要使用线程池&/b&&/p&&p&避免频繁地创建和销毁线程,达到线程对象的重用。另外,使用线程池还可以根据项目灵活地控制并发的数目。&/p&&p&&b&17、怎么检测一个线程是否持有对象监视器&/b&&/p&&p&我也是在网上看到一道多线程面试题才知道有方法可以判断某个线程是否持有对象监视器:Thread类提供了一个holdsLock(Object obj)方法,当且仅当对象obj的监视器被某条线程持有的时候才会返回true,注意这是一个static方法,这意味着“某条线程”指的是当前线程。&/p&&p&&b&18、synchronized和ReentrantLock的区别&/b&&/p&&p&synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:&br&(1)ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁&br&(2)ReentrantLock可以获取各种锁的信息&br&(3)ReentrantLock可以灵活地实现多路通知&br&另外,二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加锁,synchronized操作的应该是对象头中mark word,这点我不能确定。&/p&&p&&b&19、ConcurrentHashMap的并发度是什么&/b&&/p&&p&ConcurrentHashMap的并发度就是segment的大小,默认为16,这意味着最多同时可以有16条线程操作ConcurrentHashMap,这也是ConcurrentHashMap对Hashtable的最大优势,任何情况下,Hashtable能同时有两条线程获取Hashtable中的数据吗?&/p&&p&&b&20、ReadWriteLock是什么&/b&&/p&&p&首先明确一下,不是说ReentrantLock不好,只是ReentrantLock某些时候有局限。如果使用ReentrantLock,可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致,但这样,如果线程C在读数据、线程D也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。&br&因为这个,才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口,ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。&/p&&p&&b&21、FutureTask是什么&/b&&/p&&p&这个其实前面有提到过,FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然,由于FutureTask也是Runnable接口的实现类,所以FutureTask也可以放入线程池中。&/p&&p&&b&22、Linux环境下如何查找哪个线程使用CPU最长&/b&&/p&&p&这是一个比较偏实践的问题,这种问题我觉得挺有意义的。可以这么做:&br&(1)获取项目的pid,jps或者ps -ef | grep java,这个前面有讲过&br&(2)top -H -p pid,顺序不能改变&br&这样就可以打印出当前的项目,每条线程占用CPU时间的百分比。注意这里打出的是LWP,也就是操作系统原生线程的线程号,我笔记本山没有部署Linux环境下的Java工程,因此没有办法截图演示,网友朋友们如果公司是使用Linux环境部署项目的话,可以尝试一下。&br&使用”top -H -p pid”+”jps pid”可以很容易地找到某条占用CPU高的线程的线程堆栈,从而定位占用CPU高的原因,一般是因为不当的代码操作导致了死循环。&br&最后提一点,”top -H -p pid”打出来的LWP是十进制的,”jps pid”打出来的本地线程号是十六进制的,转换一下,就能定位到占用CPU高的线程的当前线程堆栈了。&/p&&p&&b&23、Java编程写一个会导致死锁的程序&/b&&/p&&p&第一次看到这个题目,觉得这是一个非常好的问题。很多人都知道死锁是怎么一回事儿:线程A和线程B相互等待对方持有的锁导致程序无限死循环下去。当然也仅限于此了,问一下怎么写一个死锁的程序就不知道了,这种情况说白了就是不懂什么是死锁,懂一个理论就完事儿了,实践中碰到死锁的问题基本上是看不出来的。&br&真正理解什么是死锁,这个问题其实不难,几个步骤:&br&(1)两个线程里面分别持有两个Object对象:lock1和lock2。这两个lock作为同步代码块的锁;&br&(2)线程1的run()方法中同步代码块先获取lock1的对象锁,Thread.sleep(xxx),时间不需要太多,50毫秒差不多了,然后接着获取lock2的对象锁。这么做主要是为了防止线程1启动一下子就连续获得了lock1和lock2两个对象的对象锁&br&(3)线程2的run)(方法中同步代码块先获取lock2的对象锁,接着获取lock1的对象锁,当然这时lock1的对象锁已经被线程1锁持有,线程2肯定是要等待线程1释放lock1的对象锁的&br&这样,线程1″睡觉”睡完,线程2已经获取了lock2的对象锁了,线程1此时尝试获取lock2的对象锁,便被阻塞,此时一个死锁就形成了。代码就不写了,占的篇幅有点多。&/p&&p&&b&24、怎么唤醒一个阻塞的线程&/b&&/p&&p&如果线程是因为调用了wait()、sleep()或者join()方法而导致的阻塞,可以中断线程,并且通过抛出InterruptedException来唤醒它;如果线程遇到了IO阻塞,无能为力,因为IO是操作系统实现的,Java代码并没有办法直接接触到操作系统。&/p&&p&&b&25、不可变对象对多线程有什么帮助&/b&&/p&&p&前面有提到过的一个问题,不可变对象保证了对象的内存可见性,对不可变对象的读取不需要进行额外的同步手段,提升了代码执行效率。&/p&&p&&b&26、什么是多线程的上下文切换&/b&&/p&&p&多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。&/p&&p&&b&27、如果你提交任务时,线程池队列已满,这时会发生什么&/b&&/p&&p&如果你使用的LinkedBlockingQueue,也就是无界队列的话,没关系,继续添加任务到阻塞队列中等待执行,因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列,可以无限存放任务;如果你使用的是有界队列比方说ArrayBlockingQueue的话,任务首先会被添加到ArrayBlockingQueue中,ArrayBlockingQueue满了,则会使用拒绝策略RejectedExecutionHandler处理满了的任务,默认是AbortPolicy。&/p&&p&&b&28、Java中用到的线程调度算法是什么&/b&&/p&&p&抢占式。一个线程用完CPU之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。&/p&&p&&b&29、Thread.sleep(0)的作用是什么&/b&&/p&&p&这个问题和上面那个问题是相关的,我就连在一起了。由于Java采用抢占式的线程调度算法,因此可能会出现某条线程常常获取到CPU控制权的情况,为了让某些优先级比较低的线程也能获取到CPU控制权,可以使用Thread.sleep(0)手动触发一次操作系统分配时间片的操作,这也是平衡CPU控制权的一种操作。&/p&&p&&b&30、什么是自旋&/b&&/p&&p&很多synchronized里面的代码只是一些很简单的代码,执行时间非常快,此时等待的线程都加锁可能是一种不太值得的操作,因为线程阻塞涉及到用户态和内核态切换的问题。既然synchronized里面的代码执行地非常快,不妨让等待锁的线程不要被阻塞,而是在synchronized的边界做忙循环,这就是自旋。如果做了多次忙循环发现还没有获得锁,再阻塞,这样可能是一种更好的策略。&/p&&p&&b&31、什么是Java内存模型&/b&&/p&&p&Java内存模型定义了一种多线程访问Java内存的规范。Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几部分内容:&br&(1)Java内存模型将内存分为了主内存和工作内存。类的状态,也就是类之间共享的变量,是存储在主内存中的,每次Java线程用到这些主内存中的变量的时候,会读一次主内存中的变量,并让这些内存在自己的工作内存中有一份拷贝,运行自己线程代码的时候,用到这些变量,操作的都是自己工作内存中的那一份。在线程代码执行完毕之后,会将最新的值更新到主内存中去&br&(2)定义了几个原子操作,用于操作主内存和工作内存中的变量&br&(3)定义了volatile变量的使用规则&br&(4)happens-before,即先行发生原则,定义了操作A必然先行发生于操作B的一些规则,比如在同一个线程内控制流前面的代码一定先行发生于控制流后面的代码、一个释放锁unlock的动作一定先行发生于后面对于同一个锁进行锁定lock的动作等等,只要符合这些规则,则不需要额外做同步措施,如果某段代码不符合所有的happens-before规则,则这段代码一定是线程非安全的&/p&&p&&b&32、什么是CAS&/b&&/p&&p&CAS,全称为Compare and Set,即比较-设置。假设有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才会将内存值修改为B并返回true,否则什么都不做并返回false。当然CAS一定要volatile变量配合,这样才能保证每次拿到的变量是主内存中最新的那个值,否则旧的预期值A对某条线程来说,永远是一个不会变的值A,只要某次CAS操作失败,永远都不可能成功。&/p&&p&&b&33、什么是乐观锁和悲观锁&/b&&/p&&p&(1)乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-设置这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。&br&(2)悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。&/p&&p&&b&34、什么是AQS&/b&&/p&&p&简单说一下AQS,AQS全称为AbstractQueuedSychronizer,翻译过来应该是抽象队列同步器。&br&如果说java.util.concurrent的基础是CAS的话,那么AQS就是整个Java并发包的核心了,ReentrantLock、CountDownLatch、Semaphore等等都用到了它。AQS实际上以双向队列的形式连接所有的Entry,比方说ReentrantLock,所有等待的线程都被放在一个Entry中并连成双向队列,前面一个线程使用ReentrantLock好了,则双向队列实际上的第一个Entry开始运行。&br&AQS定义了对双向队列所有的操作,而只开放了tryLock和tryRelease方法给开发者使用,开发者可以根据自己的实现重写tryLock和tryRelease方法,以实现自己的并发功能。&/p&&p&&b&35、单例模式的线程安全性&/b&&/p&&p&老生常谈的问题了,首先要说的是单例模式的线程安全意味着:某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法,我总结一下:&br&(1)饿汉式单例模式的写法:线程安全&br&(2)懒汉式单例模式的写法:非线程安全&br&(3)双检锁单例模式的写法:线程安全&/p&&p&&b&36、Semaphore有什么作用&/b&&/p&&p&Semaphore就是一个信号量,它的作用是限制某段代码块的并发数。Semaphore有一个构造函数,可以传入一个int型整数n,表示某段代码最多只有n个线程可以访问,如果超出了n,那么请等待,等到某个线程执行完毕这段代码块,下一个线程再进入。由此可以看出如果Semaphore构造函数中传入的int型整数n=1,相当于变成了一个synchronized了。&/p&&p&&b&37、Hashtable的size()方法中明明只有一条语句”return count”,为什么还要做同步?&/b&&/p&&p&这是我之前的一个困惑,不知道大家有没有想过这个问题。某个方法中如果有多条语句,并且都在操作同一个类变量,那么在多线程环境下不加锁,势必会引发线程安全问题,这很好理解,但是size()方法明明只有一条语句,为什么还要加锁?&br&关于这个问题,在慢慢地工作、学习中,有了理解,主要原因有两点:&br&(1)同一时间只能有一条线程执行固定类的同步方法,但是对于类的非同步方法,可以多条线程同时访问。所以,这样就有问题了,可能线程A在执行Hashtable的put方法添加数据,线程B则可以正常调用size()方法读取Hashtable中当前元素的个数,那读取到的值可能不是最新的,可能线程A添加了完了数据,但是没有对size++,线程B就已经读取size了,那么对于线程B来说读取到的size一定是不准确的。而给size()方法加了同步之后,意味着线程B调用size()方法只有在线程A调用put方法完毕之后才可以调用,这样就保证了线程安全性&br&(2)CPU执行代码,执行的不是Java代码,这点很关键,一定得记住。Java代码最终是被翻译成汇编代码执行的,汇编代码才是真正可以和硬件电路交互的代码。即使你看到Java代码只有一行,甚至你看到Java代码编译之后生成的字节码也只有一行,也不意味着对于底层来说这句语句的操作只有一个。一句”return count”假设被翻译成了三句汇编语句执行,完全可能执行完第一句,线程就切换了。&/p&&p&&b&38、线程类的构造方法、静态块是被哪个线程调用的&/b&&/p&&p&这是一个非常刁钻和狡猾的问题。请记住:线程类的构造方法、静态块是被new这个线程类所在的线程所调用的,而run方法里面的代码才是被线程自身所调用的。&br&如果说上面的说法让你感到困惑,那么我举个例子,假设Thread2中new了Thread1,main函数中new了Thread2,那么:&br&(1)Thread2的构造方法、静态块是main线程调用的,Thread2的run()方法是Thread2自己调用的&br&(2)Thread1的构造方法、静态块是Thread2调用的,Thread1的run()方法是Thread1自己调用的&/p&&p&&b&39、同步方法和同步块,哪个是更好的选择&/b&&/p&&p&同步块,这意味着同步块之外的代码是异步执行的,这比同步整个方法更提升代码的效率。请知道一条原则:同步的范围越少越好。&br&借着这一条,我额外提一点,虽说同步的范围越少越好,但是在Java虚拟机中还是存在着一种叫做锁粗化的优化方法,这种方法就是把同步范围变大。这是有用的,比方说StringBuffer,它是一个线程安全的类,自然最常用的append()方法是一个同步方法,我们写代码的时候会反复append字符串,这意味着要进行反复的加锁-&解锁,这对性能不利,因为这意味着Java虚拟机在这条线程上要反复地在内核态和用户态之间进行切换,因此Java虚拟机会将多次append方法调用的代码进行一个锁粗化的操作,将多次的append的操作扩展到append方法的头尾,变成一个大的同步块,这样就减少了加锁–&解锁的次数,有效地提升了代码执行的效率。&/p&&p&&b&40、高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池?&/b&&/p&&p&这是我在并发编程网上看到的一个问题,把这个问题放在最后一个,希望每个人都能看到并且思考一下,因为这个问题非常好、非常实际、非常专业。关于这个问题,个人看法是:&br&(1)高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换&br&(2)并发不高、任务执行时间长的业务要区分开看:&br&a)假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以加大线程池中的线程数目,让CPU处理更多的业务&br&b)假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换&br&(3)并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-d77aaf29b5068feace82_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1270& data-rawheight=&847& class=&origin_image zh-lightbox-thumb& width=&1270& data-original=&https://pic4.zhimg.com/v2-d77aaf29b5068feace82_r.jpg&&&/figure&&p&&/p&
前言个人认为,学习,内容越多、越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的。这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题。 这些多线程的问题,有些来源于各大网站、有些来源于自己的思考。可能有些…
&figure&&img src=&https://pic2.zhimg.com/v2-a7b78b986bff_b.jpg& data-rawwidth=&900& data-rawheight=&383& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic2.zhimg.com/v2-a7b78b986bff_r.jpg&&&/figure&&h2&一、前言&/h2&&blockquote&只有光头才能变强&/blockquote&&p&回顾前面:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s%3F__biz%3DMzI4Njg5MDA5NA%3D%3D%26mid%3D%26idx%3D1%26sn%3D1eb04bad5646%26chksm%3Debd74270dca0cb663beb878ae31e39c3cc14bc56f1db62f426f5b4cb34b9a804a0bf7cbd9a27%23rd& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&广州三本找Java实习经历&/a&&/li&&/ul&&p&上一篇写了自己面试的经历和一些在面试的时候遇到的题目(笔试题和面试题)。&/p&&p&我在面试前针对Java基础也花了不少的时间,期间也将自己写过的博文粗略地刷了一遍,同时也在网上&b&找了不少比较好的资料&/b&(部分是没看完的)。在这里给大家分享一下~~~&/p&&p&这是我刷完自己写过的笔记写的一篇&b&文章导航&/b&,针对于PC端的:&a href=&https://link.zhihu.com/?target=https%3A//zhongfucheng.bitcron.com/post/shou-ji/pcduan-wen-zhang-dao-hang& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&zhongfucheng.bitcron.com&/span&&span class=&invisible&&/post/shou-ji/pcduan-wen-zhang-dao-hang&/span&&span class=&ellipsis&&&/span&&/a&。&b&比较重要的知识点也画了思维导图&/b&,后面新发的文章也会补充上去的。&/p&&p&可能会感兴趣的资料:&/p&&ul&&li&思维导图原图:&a href=&https://link.zhihu.com/?target=https%3A//zhongfucheng.bitcron.com/post/shou-ji/nao-tu-da-quan& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&zhongfucheng.bitcron.com&/span&&span class=&invisible&&/post/shou-ji/nao-tu-da-quan&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&视频网盘:&a href=&https://link.zhihu.com/?target=https%3A//zhongfucheng.bitcron.com/post/shou-ji/shi-pin-wang-pan& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&zhongfucheng.bitcron.com&/span&&span class=&invisible&&/post/shou-ji/shi-pin-wang-pan&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&二、在学习的时候整理的面试题&/h2&&p&之前在学习或者整理知识点的时候也喜欢去找找面试题看,以下是我个人整理的面试题:&/p&&h2&2.1集合&/h2&&ol&&li&ArrayList和Vector的区别&/li&&li&HashMap和Hashtable的区别&/li&&li&List和Map的区别&/li&&li&Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()?&/li&&li&Collection和Collections的区别&/li&&li&说出ArrayList,LinkedList的存储性能和特性&/li&&li&Enumeration和Iterator接口的区别&/li&&li&ListIterator有什么特点&/li&&li&并发集合类是什么?&/li&&li&Java中HashMap的key值要是为类对象则该类需要满足什么条件?&/li&&li&ArrayList集合加入1万条数据,应该怎么提高效率&/li&&li&与Java集合框架相关的有哪些最好的实践&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/3696& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Java集合总结【面试题+脑图】,将知识点一网打尽!&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/3696& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.2Servlet+Tomcat面试题&/h2&&ol&&li&Tomcat的缺省端口是多少,怎么修改&/li&&li&Tomcat 有哪几种Connector 运行模式(优化)?&/li&&li&Tomcat有几种部署方式&/li&&li&Servlet生命周期&/li&&li&get方式和post方式有何区别&/li&&li&doGet与doPost方法的两个参数是什么&/li&&li&获取页面的元素的值有几种方式,分别说一下&/li&&li&request.getAttribute()和request.getParameter()区别&/li&&li&forward和redirect的区别&/li&&li&tomcat容器是如何创建servlet类实例?用到了什么原理&/li&&li&什么是cookie?Session和cookie有什么区别?&/li&&li&Servlet安全性问题&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/9518& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Tomcat+Servlet面试题都在这里&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/9518& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.3JSP面试题&/h2&&ol&&li&jsp静态包含和动态包含的区别&/li&&li&jsp有哪些内置对象?作用分别是什么?&/li&&li&jsp和servlet的区别、共同点、各自应用的范围?&/li&&li&属性作用域范围&/li&&li&写出5种JSTL常用标签&/li&&li&写一个自定义标签要继承什么类&/li&&li&JSP是如何被执行的?执行效率比SERVLET低吗?&/li&&li&如何避免jsp页面自动生成session对象?&/li&&li&jsp的缺点?&/li&&li&说出Servlet和CGI的区别?&/li&&li&简述JSP的设计模式。&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/5611& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&JSP面试题都在这里&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/5611& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.4JDBC&/h2&&ol&&li&JDBC操作数据库的步骤 ?&/li&&li&JDBC中的Statement 和PreparedStatement,CallableStatement的区别?&/li&&li&JDBC中大数据量的分页解决方法?&/li&&li&说说数据库连接池工作原理和实现方案?&/li&&li&Java中如何进行事务的处理?&/li&&li&写出一段JDBC连接本机MySQL数据库的代码&/li&&li&JDBC是如何实现Java程序和JDBC驱动的松耦合的?&/li&&li&execute,executeQuery,executeUpdate的区别是什么?&/li&&li&JDBC的脏读是什么?哪种数据库隔离级别能防止脏读?&/li&&li&什么是幻读,哪种隔离级别可以防止幻读?&/li&&li&JDBC的DriverManager是用来做什么的?&/li&&li&JDBC的ResultSet是什么?&/li&&li&有哪些不同的ResultSet?&/li&&li&JDBC的DataSource是什么,有什么好处&/li&&li&JDBC中存在哪些不同类型的锁?&/li&&li&java.util.Date和java.sql.Date有什么区别?&/li&&li&如果java.sql.SQLException: No suitable driver found该怎么办?&/li&&li&JDBC的RowSet是什么,有哪些不同的RowSet?&/li&&li&什么是JDBC的最佳实践?&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/2766& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&JDBC常见面试题&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/2766& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.5数据库&/h2&&ol&&li&什么是存储过程?有哪些优缺点?&/li&&li&三个范式是什么&/li&&li&什么是视图?以及视图的使用场景有哪些?&/li&&li&drop、delete与truncate分别在什么场景之下使用?&/li&&li&索引是什么?有什么作用以及优缺点?&/li&&li&什么是事务?&/li&&li&数据库的乐观锁和悲观锁是什么?&/li&&li&超键、候选键、主键、外键分别是什么?&/li&&li&SQL 约束有哪几种?&/li&&li&数据库运行于哪种状态下可以防止数据的丢失?&/li&&li&Mysql存储引擎&/li&&li&MyIASM和Innodb两种引擎所使用的索引的数据结构是什么?&/li&&li&varchar和char的区别&/li&&li&mysql有关权限的表都有哪几个&/li&&li&数据表损坏的修复方式有哪些?&/li&&li&MySQL中InnoDB引擎的行锁是通过加在什么上完成&/li&&li&数据库优化的思路&/li&&li&Oracle和Mysql的区别&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/7914& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&数据库面试题(开发者必看)&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/7914& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.6HTTP&/h2&&ol&&li&Http与Https的区别:&/li&&li&什么是Http协议无状态协议?怎么解决Http协议无状态协议?&/li&&li&URI和URL的区别&/li&&li&常用的HTTP方法有哪些?&/li&&li&HTTP请求报文与响应报文格式&/li&&li&HTTPS工作原理&/li&&li&一次完整的HTTP请求所经历的步骤&/li&&li&常见的HTTP相应状态码&/li&&li&HTTP1.1版本新特性&/li&&li&HTTP优化方案&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/1378& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&HTTP面试题都在这里&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/1378& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.7XML+JSON&/h2&&ol&&li&什么是JSON和XML&/li&&li&JSON与XML区别是什么? 有什么共同点&/li&&li&JSON、XML解析有那些方式?&/li&&li&XML和JSON优缺点&/li&&li&XPath 是什么&/li&&li&XML 命名空间是什么?它为什么很重要&/li&&li&DOM 和 和 SAX 解析器有什么区别&/li&&li&XSLT 是什么?&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/5207& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&XML+JSON面试题都在这里&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/5207& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.8过滤器和监听器面试题&/h2&&ol&&li&监听器有哪些作用和用法?&/li&&li&过滤器有哪些作用和用法?&/li&&li&web.xml 的作用?&/li&&li&Servlet 3中的异步处理指的是什么?&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/3161& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&过滤器监听器面试题都在这里&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/3161& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.9AJAX&/h2&&ol&&li&什么是AJAX,为什么要使用Ajax&/li&&li&AJAX应用和传统Web应用有什么不同?&/li&&li&请介绍一下XMLhttprequest对象&/li&&li&介绍一下XMLHttpRequest对象的常用方法和属性&/li&&li&Ajax的实现流程是怎样的?&/li&&li&AJAX请求总共有多少种CALLBACK&/li&&li&XMLHttpRequest对象在IE和Firefox中创建方式有没有不同。&/li&&li&AJAX有哪些有点和缺点?&/li&&li&请解释一下 JavaScript 的同源策略。&/li&&li&阐述一下异步加载JS。&/li&&li&如何解决跨域问题?&/li&&li&Ajax 解决浏览器缓存问题?&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/1898& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&AJAX面试题都在这里&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/1898& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.10Hibernate&/h2&&ol&&li&Hibernate工作原理及为什么要用?&/li&&li&Hibernate是如何延迟加载(懒加载)?&/li&&li&Hibernate中怎样实现类之间的关系?(如:一对多、多对多的关系)&/li&&li&hibernate的三种状态之间如何转换&/li&&li&比较hibernate的三种检索策略优缺点&/li&&li&hibernate都支持哪些缓存策略&/li&&li&hibernate里面的sorted collection 和ordered collection有什么区别&/li&&li&说下Hibernate的缓存机制&/li&&li&Hibernate的查询方式有几种&/li&&li&如何优化Hibernate?&/li&&li&谈谈Hibernate中inverse的作用&/li&&li&JDBC hibernate 和 ibatis 的区别&/li&&li&在数据库中条件查询速度很慢的时候,如何优化?&/li&&li&什么是SessionFactory,她是线程安全么&/li&&li&get和load区别&/li&&li&persist和save的区别&/li&&li&merge的含义&/li&&li&主键生成策略有哪些&/li&&li&简述hibernate中getCurrentSession和openSession区别&/li&&li&Hibernate中的命名SQL查询指的是什么?&/li&&li&可不可以将Hibernate的实体类定义为final类?&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/5882& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Hibernate最全面试题&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/5882& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&2.11Mybatis&/h2&&ol&&li&#{}和${}的区别是什么?&/li&&li&当实体类中的属性名和表中的字段名不一样 ,怎么办 ?&/li&&li&如何获取自动生成的(主)键值?&/li&&li&在mapper中如何传递多个参数?&/li&&li&Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?&/li&&li&Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?&/li&&li&为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?&/li&&li&通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?&/li&&li&Mybatis比IBatis比较大的几个改进是什么&/li&&li&接口绑定有几种实现方式,分别是怎么实现的?&/li&&li&Mybatis是如何进行分页的?分页插件的原理是什么?&/li&&li&简述Mybatis的插件运行原理,以及如何编写一个插件&/li&&li&Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?&/li&&li&Mybatis都有哪些Executor执行器?它们之间的区别是什么?&/li&&li&MyBatis与Hibernate有哪些不同?&/li&&/ol&&p&答案:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/8579& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Mybatis常见面试题&/a&:&a href=&https://link.zhihu.com/?target=https%3A//segmentfault.com/a/8579& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&segmentfault.com/a/1190&/span&&span class=&invisible&&&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&三、网上优质的面试题&/h2&&p&以下基本都是我看过,或者没看完的优质面试题博文(也有部分没有看,但觉得不错的面试题)~~~&/p&&h2&3.1有答案的面试题&/h2&&p&一、优质面试题整理---1:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=http%3A//www.cnblogs.com/lanxuezaipiao/p/3371224.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cnblogs.com/lanxuezaipi&/span&&span class=&invisible&&ao/p/3371224.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&二、优质面试题整理---2(里边有7个部分的):&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=http%3A//www.cnblogs.com/wmyskxz/p/9070737.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cnblogs.com/wmyskxz/p/9&/span&&span class=&invisible&&070737.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&三、优质面试题整理---3:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//blog.csdn.net/jackfrued/article/details/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&blog.csdn.net/jackfrued&/span&&span class=&invisible&&/article/details/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&四、优质面试题整理---4:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/jl8K-1DW2L2JMl4DQ-aMIA& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&mp.weixin.qq.com/s/jl8K&/span&&span class=&invisible&&-1DW2L2JMl4DQ-aMIA&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&五、优质面试题整理---5:&/p&&ul&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/23&/span&&span class=&invisible&&533393&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&六、优质面试题整理---6(牛客网120题):&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//www.nowcoder.com/ta/review-java/review%3Fquery%3D%26asc%3Dtrue%26order%3D%26page%3D1& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&nowcoder.com/ta/review-&/span&&span class=&invisible&&java/review?query=&asc=true&order=&page=1&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&七、优质面试题整理---7:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//www.cnblogs.com/w/p/8549333.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&cnblogs.com/w&/span&&span class=&invisible&&/p/8549333.html&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&3.2没有答案的面试题&/h2&&p&此部分大多数没有答案的,但都是比较优质的面试题&/p&&p&推荐一:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//www.jianshu.com/p/a07d1d4004b0& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&jianshu.com/p/a07d1d400&/span&&span class=&invisible&&4b0&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&推荐二:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//juejin.im/post/5a94a8ca6fb9a& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&juejin.im/post/5a94a8ca&/span&&span class=&invisible&&6fb9a&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&推荐三:&/p&&ul&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/33&/span&&span class=&invisible&&495324&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&四、除面试题之外还要了解的地方&/h2&&p&互联网校招指南:&/p&&ul&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/24&/span&&span class=&invisible&&887478&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&程序员简历:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//github.com/geekcompany/ResumeSample/blob/master/java.md& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&github.com/geekcompany/&/span&&span class=&invisible&&ResumeSample/blob/master/java.md&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&三方协议究竟是什么?(我之前看完,&b&个人简单总结&/b&一下:如果你不是非常确定毕业前留在某间公司,就不要着急签第三方!【我是非专业人员,这方面得多自己考虑,以上是我的&b&个人&/b&对三方协议的理解】)&/p&&ul&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/27&/span&&span class=&invisible&&812661&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&zhuanlan.zhihu.com/p/27&/span&&span class=&invisible&&251453&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&&a href=&https://www.zhihu.com/question//answer/& class=&internal&&&span class=&invisible&&https://www.&/span&&span class=&visible&&zhihu.com/question/5583&/span&&span class=&invisible&&0264/answer/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&li&&a href=&https://www.zhihu.com/question//answer/& class=&internal&&&span class=&invisible&&https://www.&/span&&span class=&visible&&zhihu.com/question/2641&/span&&span class=&invisible&&44015/answer/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&p&简历投递平台(我投递过的):&/p&&ul&&li&BOSS直聘&/li&&li&前程无忧&/li&&li&实习憎&/li&&/ul&&p&优质的面经+资料:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=http%3A//www.54tianzhisheng.cn//Interview-summary/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&54tianzhisheng.cn/2017/&/span&&span class=&invisible&&09/17/Interview-summary/&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&&h2&五、总结&/h2&&p&网上的资源还是多呀,上面基本都是我在逛博客,找资料的时候积累收藏起来的。当然了,网上的资源很多很多,如果你也收藏了自认为比较好的资源,不妨在评论区分享出来一起学习学习~~&/p&&p&这些网上这么多的面试题也不可能全部看完,根据自己的情况来看吧。看面试题也是校验自己是否真正理解了这个知识点,也很有可能会有新的收获。&/p&&p&最后,祝在找工作的朋友们能找到一份心仪的工作,在工作的朋友们能够加薪,在读书的朋友们学业进步哈~~&/p&&blockquote&如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以&b&关注微信公众号:Java3y&/b&。为了大家方便,刚新建了一下&b&qq群:&/b&,大家也可以去交流交流。谢谢支持了!希望能多介绍给其他有需要的朋友&/blockquote&&p&&b&文章的目录导航&/b&:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&zhongfucheng.bitcron.com&/span&&span class=&invisible&&/post/shou-ji/wen-zhang-dao-hang&/span&&span class=&ellipsis&&&/span&&/a&&/li&&/ul&
一、前言只有光头才能变强回顾前面:上一篇写了自己面试的经历和一些在面试的时候遇到的题目(笔试题和面试题)。我在面试前针对Java基础也花了不少的时间,期间也将自己写过的博文粗略地刷了一遍,同时也在网上找了不少比较好的资料(…
&p&推特上有这么一号人物:&b&James Fridman&/b&&/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-3859dbbf19aa9c0d14a0dbf6e27d137e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&357& data-rawheight=&436& class=&content_image& width=&357&&&/figure&&p&他特别乐于在网上帮网友P图,而且有求必应,他P图的手法倒称不上多么精美,甚至很多图片看起来很假,可这些图片已经为他吸引到了144万粉丝,原因就是一个字--&b&贱&/b&。&/p&&p&你能把后面的瀑布P得更大更近吗? &/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-2611a51cef5cf233feb605_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/50/v2-2611a51cef5cf233feb605_r.jpg&&&/figure&&p&你能加点什么,让我朋友像看到什么被吓跑了吗? &/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-80a76b16dfd5521babb98ff97effe43e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/50/v2-80a76b16dfd5521babb98ff97effe43e_r.jpg&&&/figure&&p&能把我的右腿拉长吗?&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-91d353a798a65ff8f9a322cfdab6ac6f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/50/v2-91d353a798a65ff8f9a322cfdab6ac6f_r.jpg&&&/figure&&p&所有朋友都说我的脖子像长颈鹿,能不能帮我改一下?&/p&&p&James:你朋友错了,你的脖子很好,长颈鹿的脖子应该是这样。 &/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-6fe9e893c34a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1080& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic4.zhimg.com/50/v2-6fe9e893c34a_r.jpg&&&/figure&&p&你能让我朋友看起来不那么尴尬吗? &/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-f507df2e1a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic1.zhimg.com/50/v2-f507df2e1a_r.jpg&&&/figure&&p&能让我们看起来一样高吗?&/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-b8a98fd670aaabf88cce1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/50/v2-b8a98fd670aaabf88cce1_r.jpg&&&/figure&&p&给我加点胡子。&/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-252fdcc771cc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/50/v2-252fdcc771cc_r.jpg&&&/figure&&p&我希望在亲一只恐龙,最好是犹他龙。 &/p&&figure&&img src=&https://pic3.zhimg.com/50/v2-bff70acc3c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/50/v2-bff70acc3c_r.jpg&&&/figure&&p&我很喜欢这张照片,但是我不喜欢后面那个小孩,能不能帮我去掉?&/p&&p&James:可是我喜欢。 &/p&&figure&&img src=&https://pic2.zhimg.com/50/v2-0eb33efb85a216f5c462a9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic2.zhimg.com/50/v2-0eb33efb85a216f5c462a9_r.jpg&&&/figure&&p&能不能让裙子长点? &/p&&figure&&img src=&https://pic1.zhimg.com/50/v2-ddbefc91096b6aad1fd7c88ea1672276_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1024& data-rawheight=&1024& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic1.zhimg.com/50/v2-ddbefc91096b6aad1fd7c88ea1672276_r.jpg&&&/figure&&p&能不能让我看起来不那么幼稚?&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-faff1cdbb0d1_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/50/v2-faff1cdbb0d1_r.jpg&&&/figure&&p&能不能让我看起来年轻点?&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-494db8bedb0e46957fd6df_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/50/v2-494db8bedb0e46957fd6df_r.jpg&&&/figure&&p&能不能让我女朋友把眼睛闭上?&/p&&figure&&img src=&https://pic4.zhimg.com/50/v2-f790c94c376e2e841007_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&640& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic4.zhimg.com/50/v2-f790c94c376e2e841007_r.jpg&&&/figure&&p&能不能帮我处理下背景里那个人? &/p&&figure&&img src=&https://pic3.zhi

我要回帖

更多关于 qualifier注解 的文章

 

随机推荐