|
線程是指進程中的一個單一順序的控制流,是操作系統能夠調度的最小單位,一個進程中可以有多條線程,分別執行不同的任務。線程有內核線程和用戶線程之分,但在本文中僅指內核線程。在軟件開發中,使用線程有以下好處:
1、在多核或多路 CPU 的機器上多線程程序能夠并發執行,提高運算速度;
2、把 I/O,人機交互等與密集運算部分分離,提升 I/O 吞吐量和增進用戶體驗。
線程的缺點也很明顯:
1、創建一條線程需要較大的內存開銷,導致不能創建海量的線程;
2、線程由操作系統調度(分配時間片),線程切換的 CPU 成本比較高,導致大量線程存在時大量 CPU 資源消耗在線程切換上;
3、同一進程的多條線程共享全部系統資源,在多線程間共享資源需要進入加鎖,大量的鎖開銷不提,重要的是加大了編寫程序的復雜性,這一點你看看有多少書名含有“多線程”三個字就明白寫個多線程應用有多難了;
4、 I/O 方面,多線程幫助有限,以 TCP Socket Server 為例,如果每一個 client connection 由一條專屬的線程服務,那么這個 server 可能并發量很難超過 1000。為了進一步解決并發帶來的問題,現代服務器都使用 event-driven i/o 了。
event-driven i/o 解決了并發量的問題,但引入了“代碼被回調函數分割得零零碎碎”的問題。特別是當 event-driven i/o 跟 multi-threading 結合在一起的時候,麻煩就倍增了。解決這個問題的辦法就使用綠色線程,綠色線程可以在同一個進程中成千上萬地存在,從而可以在異步 I/O 上封裝出同步的 APIs,典型的就是用基于 greenlet + libevent 開發的 python 庫 gevent。綠色線程的缺陷在于操作系統不知道它的存在,需要用戶進行調度,也就無法利用到多核或多路 CPU 了。為了解決這個問題,很多大牛都做出了巨大的努力,并且成果斐然,scala、google go 和 rust 都較好地解決了問題,下文以 rust 的并發模型為例講一下。
rust 提出一個 Task 的概念,Task 有一個入口函數,也有自己的棧,并擁有進程堆內存的一部分,為方便理解,你可以把它看作一條綠色線程。rust 進程可以創建成千上萬個 Tasks,它們由內建的調度器進行調度,因為 Tasks 之間并不共享數據,只通過 channels/ports 通信,所以它們是可并行程度很高。rust 程序啟動時會生成若干條(數量由 CPU 核數決定或運行時指定)線程,這些線程并行執行 Tasks,從而利用多個 CPU 核心。
如 上圖,rust 應用程序不停地 spawn 出一個又一個 Tasks,它們由 tasks 調度器管理,在適當的時機,調度器會把某一個 Task 分配給原生線程執行,如果這個 Task 進入 I/O 等待或主動讓出 CPU(sleep),那么這個 Task 會被交回給調度器,而相應的原生線程會執行另一個新分派的 Task。盡管使用 rust 編程語言是不能創建線程的(直接調用 C 函數不算),但 rust 應用程序實際上是多線程的(一般情況下),它能夠充分地利用多核或多路 CPU。
綜上,類似 rust 的 Task 的概念是比線程更好的并發模型,更安全,編寫的代碼也更加容易維護(關于維護性,我相信寫過 gevent 程度或 go 程序的同學會認同的)。線程當然不會消亡,但隨著 scala/go/rust 的成熟,在可以預見的將來,線程會退到它呆著的角落:遠離普通程序員,只有少數人需要了解它的細節。
C++ 在 2011 年其實風頭甚勁,C++2011 標準出臺,gcc/msvc/clang 都很快速地支持了許多新特性,新興的移動設備的性能較差,更是 C++ 的新舞臺,在這個時候唱衰 C++,壓力很大。我使用 C++ 年頭不少,但除了在校的時候寫過兩個小游戲參加過兩個比賽(分別是面向社會和面向大學生的)弄些證書好找工作以外,在工作中只用過大概不到一年半,做《斬 魂》(http://zh.163.com)的早期版本,寫了服務器端的幾條進程和客戶端的 GameAI 部分。經驗少,而且寫得不好,所以基本上有人在 weibo 上問我 C++ 的問題,我都是轉發給 @bnu_chenshuo 和 @miloyip 等真正的行家去回答的。所以實際上今天寫這一篇,我底氣很是不足,但是朋友們給前兩篇很大面子,弄得我騎虎難下,只好硬著頭皮寫了。
前 文提到 C++ 的新標準,很有必要提一下標準化對 C++ 的影響。首先我們要肯定標準定制對 C++ 的積極作用,但標準化過程中的超長流程,一次次將 C++ 推向深淵。C++ 的第一個標準是 1998 年的 ISO/IEC 14882:1998,距離整個 90 年代最流行的 C++ 程序庫 MFC(Microsoft Foundation Class Library)的第一個版本發行時間已經整整 6 年。1998 年,MFC 版本號為 6.0,與其一起發布的 Visual C++ 6.0 占有了巨大的市場。因為 MFC 發布得標準制定的時間早,所以 MFC 內部實現了許多后來標準庫里也有的組件,比如各種數據結構容器。VC6 的市場占有率讓 windows 平臺下開發的許多 C++ 程序員甚至不知道有 STL,同時也無視 C++98 標準,從更兼容標準的 VC2002/2003 的市場占有率就可以看出來,直到今天,我知道國內不少公司還是只用 VC6 的。
其實在 90 年代,計算機的運算能力有限,市場上非常需要一款性能較高、抽象較強的編程語言,C++ 獲得了成功,但它標準化的時間過長,造成各種編譯器有各自互不兼容的“方言”,成了它的第一個軟肋。第一個瞄準這個軟肋的就是 java,java 在 1995 年推出,雖然性能稍遜,但它有更高的抽象能力、也更安全,并且更容易跨平臺,所以迅速獲得了成功;第二個瞄準這個軟肋的是 C#,微軟不能推動 C++ 發展,又不愿 C++ 的市場被 java 鯨吞,于是在 2001 年推出了 C#,經過 10 年的發展和微軟大量的金錢推廣,C# 已經成功獲得了它應有的江湖地位。
雖然 java/c# 都不是善類,但 C++ 在 21 世紀的第一個十年里仍然地位穩固,這是因為 Linux 和 MacOS X 大獲成功,在這兩個平臺上 C++ 都是非常有競爭力的編程語言,C++ 自然水漲船高。但隨著 web2.0 和 web app 概念的興起,以及 CPU 的主頻進一步提升,服務器端編程語言漸漸地對執行效率不再敏感,而是更在意程序員的開發效率,眾多的腳本語言開始蠶食 C++ 的市場份額,從早期的 perl 到后期的 python/php/ruby,在 2005 年以后,C++/java/C# 等靜態類型的編譯型語言的市場份額都下降了,新興的貴族是動態語言。面對動態語言在開發效率上的強勁挑戰,C++ 社區除了在 2003 年對 C++98 做了小小的 patch,基本上睡著了,完全沒有應對之策,哦不,連應用的姿態都沒有。
進入 21 世紀的第二個十年,市場又發生了變化,云計算越走越近,也許我們中的大部分人今天還可以說只聞其聲不見其形,但 The Data Center Is the Computer 這句話大家應該覺得很務實:完成一個用戶操作,在服務器端的進程間通信次數前所未有地多。在這個十年,我們需要這樣的編程語言:
1、能充分利用現代 CPU 的計算能力,不僅僅是多個核心,更是巨大的 L1/L2/L3 Cache、超線程等;
2、能夠大量減小異步 I/O 的性能提升的同時帶來的副作用:異步編程的復雜性以及對可維護性的傷害;
兩 句話其實也可以壓縮為一句:需要有更好的并發模型的語言。一開始大家都在已有的編程語言中尋找,然后找到了 erlang,實踐證明 erlang 自有其局限,所以 google go/scala/rust 等新語言如同雨后春筍般撥地而出。C++2011 標準努力降低 C++ 的編程難度,并提供了線程庫以支持現代 CPU,如果在 2005 年,這個標準絕對有競爭力,但在今天,它只能成為新的編程語言的墊腳石。正如 IE 最大的用處是用來下載其它瀏覽器,不久之后,也許會流行新的冷笑話:C++ 最大的用處就是用來實現其它編程語言。
市場一直在尋找一門中間的高級 語言,它上承 C 語言和匯編語言,下啟腳本語言。C++ 最先搶占了高地,并在與 java/c# 的爭斗中不落下風,但新的十年,它的對手又增加了 google go/scala/rust 等新銳,并且新的標準不可能在兩三年內再次出臺,兩三年內新銳成長起來后,留給它的位置就不多了。
上 文討論的基本上都是服務器編程,有必要再來看一下桌面和移動設備領域。首先看桌面軟件,rust 是 mozilla 基金會開發系統程序語言的,它的定位是部分取代 C++ 開發 firefox 的瀏覽器,所以 rust 會進入桌面開發,google go 肯定會順道啃一口。移動設備方面,主要是 android、ios 和 windows phone,隨著移動設備性能增強,編譯型語言加腳本的模式就會占大頭,編譯型語言方面主要是 C++ 和 Objective-C 在競爭,C++ 會占上風(但需求量遠遠小于腳本,從 lua 在 2011 年的增長速度可以印證),但是誰知道 rust 之類的會不會進入移動設備呢,畢竟移動設備的 CPU 核心也越來越多了呀,C++ 還是前景堪憂。
回首 C++ 的 30 年,展望它的未來,總結起來可能就是:標準化流程拖死人了。如果不是 15 年不能標準化,java/c# 的攪局可能不會出現;如果在 2005 年能夠應對動態語言……如果云時代有更好的并發模型……
題 外話:java/c# 不會有 C++ 的問題,因為它們有自己的平臺,有巨大的財富支撐。特別是平臺的作用非常巨大,你可以想像一下如果 Adobe 有自己的瀏覽器或手機操作系統 ActionScript/MXML 會不會是今天的境地;也可以想像一下 google go 的飛速發展動力是什么。
勞動密集型公司
這樣的公司以業務為導向,市場團隊在公司中占據較高的地位。每一個技術人員最終被折算到了“人天”里面去,團隊規模相對較大,所有技術人員都比較容 易被替代,能力強的可以做更多的事情,能力弱的就少做一些。通過強有力的制度、政策和流程的規約,團隊有條不紊地運作起來。業務氛圍強勢,技術通道升級較 慢,需要非常長期的積累才可以獲得豐厚的回報,諸多優秀人才脫離編碼,而潛心轉管理、談需求并獲得回報。愿意招納畢業生編碼,以減小運營成本。只鼓勵小范 圍、淺層次的創新,對于優秀的創意、想法,必須轉化為生產力才能夠被認可。
技術密集型公司
這樣的公司較為重視技術和創新,敢于在產品中使用預期能夠帶來收益的技術。公司非常愿意招聘一些有豐富研發經驗、有廣泛閱歷的程序員加入,同時也能 吸引一些比較優秀的技術人才,并且長期為公司工作。團隊人員較少,研發過程無論是從時間還是環境來看,通常比較寬松,用較少約束、任務驅動的形式,鼓勵程 序員按期完成下發的任務。技術人員層次劃分較多,不同層次技術人員在一起辦公,往往都不脫離編碼,和項目結合緊密。愿意招不同層次的研發人員,不愿意招經 驗豐富但脫離技術的人到研發團隊。
思維密集型公司
這樣的公司對研發人員思辨能力要求較高,愿意做一些創造性的產品。公司技術人員的招聘較為嚴格,更看重人員的創新氣質、解決問題的思路、建模和抽象 的能力,而對于具體的某種技術實現,并沒有很高的要求。團隊人員不多,項目壓力不大,任務給定的要求和流程約束較少,需要團隊成員較強的自主能力來解決問 題。技術人員層次劃分不多,討論氣氛濃厚,設計精益求精,創新的點子容易得到認可并嘗試實現。
你所在的公司,屬于哪一種?
漁夫 蛇 青蛙的故事
漁夫看到船邊有條蛇,口中正銜著一只青蛙。漁夫動了惻隱之心,把青蛙從蛇的口中救了出來。但漁夫又為蛇將挨餓而難過,便拿出一瓶酒,往蛇的口中滴了幾滴。 蛇高興地游走了,青蛙也為重獲新生而高興,漁夫則為自己的善舉而感到快樂。他想,這真是皆大歡喜!沒料到,僅僅過了幾分鐘,漁夫聽到有東西在叩擊他的船 板。他低頭一看,那條蛇又回來了,而且嘴里咬著兩只青蛙——它來討要更多酒的獎賞!
漁夫的本意是希望蛇不再捕捉青蛙,但是由于憐憫而給了它幾滴酒——這是獎勵而不是懲罰,結果事與愿違。你獎勵了什么行為,就會得到更多這樣的行為。所以,這則寓言要告訴我們的是,別去獎勵那些錯誤的行為。
我們再講一個企業獎勵錯誤行為的故事
一家企業制定了一個規定,如果該企業的員工加班到晚上7 點可以獲得10元錢的晚餐補助,如果加班到8點可以打出租車回家(平常5點下班)。該獎勵制度執行了一段時間之后,公司管理者竟然發現,有很多員工在正常 下班前或者很早就已經完成了工作,但是他們居然不正常下班而是留下來繼續加班,有的待到七點,有的待到八點以后。一個管理者親眼看見一個員工在下午4點前 就完成了文檔整理,然后一直在那里上網聊天一直到晚上8點。
你也行會認為這些員工鉆公司的空子有些不太好,但是這不能完全怪他們,因為早早的完成工作不見的會得到公司的獎勵,相反有意把工作拖到晚上8點之后就可以拿到打車費,并且能免費獲得一頓飯錢,多劃算呀!
管理者一定要牢記住這句話"受到獎勵的事情人們都喜歡去做" 為此管理者應該仔細檢測獎勵制度,哪些是積極的 ,哪些可能帶來消極的影響,修改掉哪些不合理的部分,通過獎勵正確的行為來獲得自己想要的結果。
美國管理專家拉伯福認為,企業在獎勵員工方面最常范的十個錯誤.
1、需要好的結果,卻獎勵了那些看上去最忙碌,工作時間最長的人
2、要求工作的質量,卻設下了不合理的完成工期
3、希望從根本上解決問題,卻獎勵那些治標不治本的人
4、要求員工對公司忠誠,卻支付高薪給新來的員工或威脅要離職的員工
5、要求事情簡單化,卻獎勵制造瑣碎和使事情復雜化的人
6、想要創造和諧的工作環境,卻獎勵那些光說不做并且經常抱怨的人
7、要求員工有創意,卻指責那些公司里有特立獨行的人
8、要求節儉,卻獎勵那些浪費資源的人
9、要求員工有團隊精神,卻犧牲團隊利益獎勵那些投機取巧的人
10、要求創新,卻獎勵保守的人,責罰未能完成的創意
如何改進我們的獎勵行為
孔子云:舉一而不能以三反,不可教也。每一個治理者都可以對照拉伯福所說的這十種錯誤,舉一反三,驗照一下自己是不是犯過類似的錯誤。例如:
1、 我們 是不是口頭上公布講究實績、注重實效,卻往往獎勵了那些專會做表面文章、投機取巧之人?
2、 我們是不是口頭上公布員工考核以業績為主,卻往往憑主觀印象評價和獎勵員工?
3、 我們是不是口頭上公布鼓勵創新,卻往往處罰了敢于創新之人?
4、 我們是不是口頭上公布鼓勵不同意見,卻往往處罰了敢于發表不同意見之人?
5、 我們是不是口頭上公布按章辦事,卻往往處罰了堅持原則的員工?
6、 我們是不是口頭上鼓勵員工勤奮工作、努力奉獻,卻往往獎勵了不干實事、專事搗鬼、鉆營之人?
總結
總之,我們每一個治理者都要牢記:“在表現與獎勵之間建立起正確的連帶關系,是改進組織運作的唯一要訣”。在考核和獎勵員工時非凡要注重的是,要注重其實 際業績,而不要注重其口頭上怎么說。不能獎勵了投機取巧,冷落了埋頭實干,否則以后我們指望誰來做事呢?
治理大師卡耐基說過:我年紀越大,就越不重視別人說些什么,我只看他們做些什么。其實中國古賢更早就說過這樣的話:“始吾于人也,聽其言而信其行;今吾于 人也,聽其言而觀其行”。在獎罰問題上,每個治理者確實不可粗心大意,草率行事。否則,“種瓜得瓜,種豆得豆”,種下了苦果可是要自己吃的!
博士
有一個博士分到一家研究所,成為學歷最高的一個人。
有一天他到單位后面的小池塘去釣魚,正好正副所長在他的一左一右,也在釣魚。
他只是微微點了點頭,這兩個本科生,有啥好聊的呢?
不一會兒,正所長放下釣竿,伸伸懶腰,蹭蹭蹭從水面上如飛地走到對面上廁所。
博士眼睛睜得都快掉下來了。水上飄?不會吧?這可是一個池塘啊。
正所長上完廁所回來的時候,同樣也是蹭蹭蹭地從水上飄回來了。
怎么回事?博士生又不好去問,自己是博士生哪!
過一陣,副所長也站起來,走幾步,蹭蹭蹭地飄過水面上廁所。這下子博士更是差點昏倒:不會吧,到了一個江湖高手集中的地方?
博士生也內急了。這個池塘兩邊有圍墻,要到對面廁所非得繞十分鐘的路,而回單位上又太遠,怎么辦?
博士生也不愿意去問兩位所長,憋了半天后,也起身往水里跨:我就不信本科生能過的水面,我博士生不能過。
只聽咚的一聲,博士生栽到了水里。
兩位所長將他拉了出來,問他為什么要下水,他問:“為什么你們可以走過去呢?”
兩所長相視一笑:“這池塘里有兩排木樁子,由于這兩天下雨漲水正好在水面下。我們都知道這木樁的位置,所以可以踩著樁子過去。你怎么不問一聲呢?”
這個故事告訴我們:學歷代表過去,只有學習力才能代表將來。尊重經驗的人,才能少走彎路。一個好的團隊,也應該是學習型的團隊。
個人理解和感悟:看學歷更要看能力
招聘廣告上面我們經常會看到“要求本科以上學歷”,很少有企業招聘的時候 是不在乎學歷的,而且在一些正規的企業里,如果沒有足夠的學歷,是不予以考慮加薪升職的。企業在人才的競爭上面出現了一種盲目攀比學歷的不良傾向,現在經 常可以看到在某些企業的官方介紹上面寫“公司的本科以上學歷占有xx比例”的字眼,,似乎聘用的人才學歷越高
越好,在職員工高學歷的越多越好。有一則消息稱研究生學歷的人比本科學歷的人平均年薪要高出2w元,從這里看出,學歷在企業招聘和考核中的重要性。
現在越來越多的人堅持考研或者讀MBA,他們認為一旦有了高的學歷就可以“春風得意馬蹄疾,一頁看遍長安花”了。目前學歷仍然是一個隱形的、力量巨大的“殺手”,生生的把沒有一紙文憑的人拒之門外。
有文憑不等于有水平,沒有學歷不等于沒有能力,大量的事實說明, 不少才華橫溢、能力卓越的人才,他們并沒有高的學歷,有的甚至沒有大學文憑,例如愛迪生、高爾基諾貝爾 比爾蓋茨 喬布斯等,這些人雖然沒有高的學歷,但是他們取得的成就是非凡的,同樣現實中生活中也能輕易的發現,很多擁有高學歷的人在工作中能力平平、毫無建樹、庸庸 碌碌的過萬了一生,管理者在選擇人才時,只能把學歷當作一種參考條件,更重要的是要看這個人的實際能力。如果企業不從實際出發,競相制定一些高學歷的規 定,對學歷的要求過為嚴格,甚至唯學歷取人,很難選拔出優秀的人才,衡量人才既要有文化程度方面的要求,更總要視履行崗位職責的能力,真正使那些有學歷, 有智慧又有能力的人得到重用.
伯 樂相馬,主要是看馬能否跑千里而不是看馬的出身。近有消息說,有些用人單位招聘人才的取向已更加務實,選才標準正在由“學歷型”向“能力型”轉變,這是一 種令人欣慰的轉變。畢竟,千里馬是跑出來的,人才是干出來的。創造業績主要不是靠職前的學歷,而是靠任職后的實踐經歷和創造性努力。但愿我們公開選拔干部 時,能夠更重任職的能力而不是更重職前的學歷。
一個人是否真正的有才能,并不能以學歷作為衡量的唯一標準,管理者在選人、用人時,不要被學歷遮住了視野,二應該把有實際能力的員工放在最重要的位置上
春節前和同事在回家的路上看到了建筑工地,不由的感慨建筑業相比軟件業來講實在是成熟太多了! 想想看,建筑師設計好圖紙,交給建筑公司(大包工頭), 大包工頭再報給小包工頭, 小包工頭隨便抓一些農民工就可以干活了! 農民工們可不懂得那么多高深的建筑原理, 對整個建筑也并不了解,可是他們只需要把自己的一磚一瓦做好,整個建筑就能做成了 -- 當然也有豆腐渣工程-- 但畢竟是少數,排除在外。
更重要的是他們根本不用擔心項目的后期客戶突然想改設計方案,客戶不會也不可能要求你把朝北的窗戶挪到南邊去,也不會要求把10層樓中的第3層和第7層扒掉重蓋。
我們這些苦苦掙扎的碼農們肯定會想, 什么時候軟件業也能這樣啊,什么時候我們也能快樂編程,按時上下班,或者以后這些底層的Labor work都讓機器人做了, 我們都去做需求,架構,設計, 然后項目按進度,高質量的完成, 大家都很happy...
但是無數的無情現實告訴教育我們:別做夢了,這是絕對不可能的, 至少在可以預見的時間段(比如50年)是不可能的, 原因就在于軟件的復雜性,在現有的技術情況下, 軟件的固有復雜性無法解決, 只有依靠我們這么碼農們去彌補。
為什么軟件這么復雜, 為什么我們無法像建筑業蓋房子,汽車業裝配汽車一樣去寫軟件?
布魯克斯 在著名的《人月神話》中提到軟件的內在復雜性, 的確,軟件系統的復雜性遠遠超過建筑業和制造業, 軟件的需求是在人的腦子中的, 用自然語言都很難完整、準備的表達出來,更不用說用計算機(好吧,更好聽的名字是”電腦“)這種原始的工具了。 不錯,我用的正是”原始“這個詞, 從二進制語言,到匯編語言,再到高級語言,其最基本的、最核心的東西依然是順序,循環,分支, 即使加上面向對象,動態語言,庫, 框架,計算機語言的本質仍然沒有改變,我們只是在已經建好的大廈上做裝飾而已。 使用這種原始的工具,怎么能夠表示復雜的需求?
程序員的出現正是為了填充這之間的巨大鴻溝,程序員需要用自己的大腦,使用極其”原始“的工具, 把無法準確表述的,尚在腦子中的需求映射到代碼上,其難度可想而知!
當然我們程序員也不笨, 在長期的斗爭中,我們學會了把一個問題用劃分為一個一個的模塊, 讓這些模塊低耦合,高內聚, 我們還學會了分層,讓各個部分的聯系達到最小, 可是所有的這些努力只是把復雜性降低了一點, 本質的復雜性依然存在。
未完待續。。。
酒宴開始。
酒杯盛酒,酒杯碰撞,這是物理層;
你要根據不同人的外貌特征找到你要敬酒的人所坐的位置,這是IP協議(網絡層);
你明白,敬酒的實際目的是加深感情,這在應用層,而這酒中的感情,才是報文的數據部分。
你和某位新見面的兄弟互相來回敬酒,這叫TCP;
你給同一位好兄弟敬酒好多次,死命灌他,他也不回禮,這叫UDP;
你對全桌的人說,來,咱們同歸于盡,這叫廣播;
你在對這一桌的人順序挨個敬酒,這叫令牌環。
你對該兄弟說,初次見面,請多關照,請問閣下尊姓大名,敬酒一杯,這叫SYN報文;
這位兄弟說,同是天涯淪落人,相逢何必曾相識,喝!這叫ACK報文;
你一看,對方的啤酒怎么沒有氣泡啊,不行,你怎么能拿茶水當啤酒呢?這叫數據校驗。
有一個兄弟過來給你桌上的領導敬酒,你說不行,領導喝多了,不能再喝了,這叫防火墻;
有一位兄弟過來敬酒,你說10分鐘里面已經喝了5杯了,達到我極限了,這叫帶寬;
而且我還沒回禮呢,現在喝不下了,先緩緩,這叫擁塞控制;
你現在要給你最好的兄弟敬酒,于是你先找到了他所在的桌子(網絡號),再找到他本人的位置(主機號);
從你要準備敬酒到敬酒完成,這叫時延,其中要經歷倒酒(發送時延)、碰杯(傳播時延)、你的兄弟被灌下(處理時延)這幾個過程。
終于,你醉了,你吐了一地,不省人事,這叫緩沖區溢出。
故事一
去過廟的人都知道,一進廟門,首先是彌陀佛,笑臉迎客,而在他的北面,則是黑口黑臉的韋陀。
但相傳在很久以前,他們并不在同一個廟里,而是分別掌管不同的廟。 彌樂佛熱情快樂,所以來的人非常多,但他什么都不在乎,丟三拉四,沒有好好的管理賬務,所以依然入不敷出。而韋陀雖然管賬是一把好手,但成天陰著個臉,太 過嚴肅,搞得人越來越少,最后香火斷絕。
佛祖在查香火的時候發現了這個問題,就將他們倆放在同一個廟里,由彌樂佛負責公關,笑迎八方客,于是香火大旺。而韋陀鐵面無私,錙珠必較,則讓他負責財務,嚴格把關。在兩人的分工合作中,廟里一派欣欣向榮景象。
故事二
在動物園里的小駱駝問媽媽:"媽媽媽媽,為什么我們的睫毛那么地長?"
駱駝媽媽說:"當風沙來的時候,長長的睫毛可以讓我們在風暴中都能看得到方向。"
小駱駝又問:"媽媽媽媽,為什么我們的背那么駝,丑死了!"
駱駝媽媽說:"這個叫駝峰,可以幫我們儲存大量的水和養分,讓我們能在沙漠里耐受十幾天的無水無食條件。"
小駱駝又問:"媽媽媽媽,為什么我們的腳掌那么厚?"
駱駝媽媽說:"那可以讓我們重重的身子不至于陷在軟軟的沙子里,便于長途跋涉啊。"
小駱駝高興壞了:"嘩,原來我們這么有用啊!!可是媽媽,為什么我們還在動物園里,不去沙漠遠足呢?"
故事三
有個魯國人擅長編草鞋,他妻子擅長織白絹。他想遷到越國去。友人對他說:“你到越國去,一定會貧窮的。”“為什么?”“草鞋,是用來穿著走路的,但越國人 習慣于赤足走路;白絹,是用來做帽子的,但越國人習慣于披頭散發。憑著你的長處,到用不到你的地方去,這樣,要使自己不貧窮,難道可能嗎?”
故事一告訴我們:其實在用人大師的眼里,沒有廢人,正如武功高手,不需名貴寶劍,摘花飛葉即可傷人,關鍵看如何運用。
故事二告訴我們:天生我才必有用,可惜現在沒人用。一個好的心態+一本成功的教材+一個無限的舞臺=成功。每個人的潛能是無限的,關鍵是要找到一個能充分發揮潛能的舞臺。
故事二告訴我們:一個人要發揮其專長,就必須適合社會環境需要。如果脫離社會環境的需要,其專長也就失去了價值
個人理解和感悟:充分發揮員工的長處
管理者的任務,簡單的說就是找到對的人,把他們放到對的地方,然后鼓勵他們充分發揮自己的創意,完成本職工作,在這個過程中管理者既要用人職場,又要容忍之短,使員工最大限度的發揮自己的才能,達到合理使用人才的目的。
正確的用人之道,就是用人的長處,即讓一個人的長處和優勢得到充分的發揮,讓一個人的短處和劣勢得到有效的避免,正所謂“人盡其才,物盡其用”“木匠手中 無爛木”“智者不用其短,而用愚人之所長也”,從某種意義上說天下沒有無用之人,一個擅長用人的管理者,能將每個人都派上用場
如何才能揚人之所長
1、管理者必須做到客觀公正。每個人都不可避免的會有自己的好惡,也會收到成見、偏見影響、管理者一定要待人寬容,心胸開闊,一切從公司的利益出發,不可錯過一個人才
2、管理者應該充分利用科學方法。人才入冰山,其優秀特質浮出水面的只有1/3 ,如果不運用一些科學的方法很難看出來,方法有很多,筆試、面試、心理測試、情景模擬、評價中心等,在使用的過程中要注意靈活運用
3、將人才放到對的位置上。根據其特點,為其提供充分展示自己能力的平臺,讓其在實際的工作中不斷鍛煉
4、適時展開具有針對性、個性化的培訓。培訓不但要補員工所短,同時應該培訓員工長處,讓員工之“長”根突出、更醒目。并讓其在你的公司里面形成一定的品牌
5、優化配置、平衡互補,取各家之“長”溶于一爐,并相互揚“長”,相互促“長”
看來看下面的一段代碼:
代碼片段1
這段代碼的輸出是什么?相信很多人都會很容易的猜到:false,因為a、b兩個對象的地址不同,用“==”比較時是false。恭喜你,答對了。
再看下面的一段代碼:
代碼片段2
你可能會回答,這沒什么不一樣啊,所以還是false。很遺憾,如果你執行上面的一段代碼,結果是true。
上面的代碼可能讓你有些意外,那好吧,再看看下面的這段代碼:
代碼片段3
結果是true嗎?很遺憾,如果你執行上面的一段代碼,結果是false。
感到吃驚嗎?那最后再看下面的一段代碼:
代碼片段4
最后的結果,可能你已經猜到了,是true。
現在我們分析一下上面的代碼。可以很容易的看出,這一系列代碼的最終目的都是用“==”對兩個對象進行比較。Java中,如果用“==”比較兩個對象結果為true,說明這兩個對象實際上是同一個對象,false說明是兩個對象。
現在,我們來看看為什么會出現上面的現象。
我們先看代碼片段4:最后的運行結果是true,說明a、b兩個對象實際上是同一個對象。但是a對象是通過調用Integer的valueOf方法創建的,而b對象是通過自動裝箱創建出來的,怎么會是同一個對象呢?難道問題在字節碼那里,畢竟Java程序是依靠虛擬器運行字節碼來實現的。
通過jdk中自帶的工具javap,解析字節碼,核心的部分摘取如下:
代碼中我們只調用了一次Integer.valueOf方法,但是字節碼中出現了兩次對Integer.valueOf方法的調用。那么另一次是哪里呢?只可能在自動裝箱時調用的。因此這段代碼實際上等價于:
現在問題就簡單了:看jdk源代碼,查看valueOf方法的具體實現:
看到這兒,上面的代碼就很明確了:對于-128到127的數字,valueOf返回的是緩存中的對象。所以兩次調用Integer.valueOf(100)返回的都是同一個對象。
我們再先看代碼片段3:根據上面的分析,代碼片段3實際上等價于以下代碼:
由于156不在-128到127范圍內,所以兩個對象都是通過new Integer()的方式創建的,所以最后結果為false。
片段1和片段2就不做具體分析了,相信讀者可以自行分析。
最后,請大家思考一下問題:通過上面的分析,了解到整數的自動裝箱是通過Integer.valueOf(int number)實現的,那么自動拆箱是如何實現的呢?
1.關于JSP標簽的好處就不再羅嗦
數據字典就是使用的下拉框,只要定義使用那個字典就會將這個字典可用的內容顯示出來
顯示字典時只要定義那個字典和屬性值就可以顯示出字典的顯示值
2.首先在web.xml中定義自定義標簽加載的引用,兩個屬性分別是引用的URI和加載路徑
3.在web-html.tld中定義自己的標簽,數據字典應用的話我們需要一個標簽庫,三個標簽。分別是,select標簽,options標簽,和現實數據字典的標簽,每個標簽都對應不同的實現類
4.實現類
實現類的作用就是在后臺拼接所需HTML標簽內容,然后由JSP進行輸出
實現類最主要的兩個方法,一個遇到這個標簽開始時輸出,一個是結束時輸出
如果需要定義屬性,可以參考實現類定義屬性,并在TLD中定義,在JSP中使用標簽時快捷鍵就可以出來這個屬性
首先是select標簽的代碼:
關于返回參數,返回具體數字也可以,不用過于糾結
然后是下拉內容實現類
具體你的字典數據從數據庫中如何存儲如何查詢,可以自定義實現
顯示的標簽實現,為了將來可以在頁面取到標簽內容值,我們定義隱藏域來保存屬性值,然后在顯示顯示內容
5.JSP中引用,直接在index.jsp中引用
需要引入相應的標簽內容,引入的方式在JSP頭部引用
標簽的屬性可以設置也可以不設置,標簽的使用和HTML標簽的使用是一樣的,定義屬性即可
6.后話
訪問項目就可以看到效果,附件是這個項目的源代碼,導入到MyEclipse中可以查看
如果想要自己設計一個大的標簽庫,可以設計一個父類,包含一些主要的屬性,例如name,id,style等屬性。然后在子類中定義自己的特有屬性
這個實現只是學習一下JSP自定義標簽使用的HelloWorld程序,然后包含了字典應用的實際例子,程序簡單,僅供參考