版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
JAVA的位運(yùn)算
關(guān)鍵字:java位運(yùn)算
Java位運(yùn)算
一,Java位運(yùn)算
1.表示方法:
在Java語言中,二進(jìn)制數(shù)使用補(bǔ)碼表示,最高位為符號(hào)位,正數(shù)的符號(hào)位為
0,負(fù)數(shù)為1。補(bǔ)碼的表示需要滿足如下要求。
⑴正數(shù)的最高位為0,其余各位代表數(shù)值本身(二進(jìn)制數(shù))。
(2)對(duì)于負(fù)數(shù),通過對(duì)該數(shù)絕對(duì)值的補(bǔ)碼按位取反,再對(duì)整個(gè)數(shù)加1。
2.位運(yùn)算符
位運(yùn)算表達(dá)式由操作數(shù)和位運(yùn)算符組成,實(shí)現(xiàn)對(duì)整數(shù)類型的二進(jìn)制數(shù)進(jìn)行位運(yùn)
算。位運(yùn)算符可以分為邏輯運(yùn)算符(包括[&、I和D及移位運(yùn)算符(包括〉、?
和>>>)。
注釋廣
?是取反運(yùn)算
首先,你要知道java中的int是32位的
其次,正數(shù)以原碼的形式存儲(chǔ),負(fù)數(shù)以補(bǔ)碼的形式存儲(chǔ)
4的二進(jìn)制是00000000000000000000000000000100
取反后得11111111111111111111111111111011
java中都是有符號(hào)數(shù),首位是1,所以是負(fù)數(shù),負(fù)數(shù)也就是補(bǔ)碼,也就是說
11111111111111111111111111111011是補(bǔ)碼
補(bǔ)碼,反碼加1后得源碼
轉(zhuǎn)換成源碼得00000000000000000000000000000101
這個(gè)數(shù)是5,加上符號(hào)就是?5
1)左移位運(yùn)竟符(<<)能將運(yùn)兌符左邊的運(yùn)算對(duì)象向左移動(dòng)運(yùn)算符右側(cè)指定的位
數(shù)(在低位補(bǔ)0)。
2)“有符號(hào)”右移位運(yùn)算符(>>)則將運(yùn)算符左邊的運(yùn)算對(duì)象向右移動(dòng)運(yùn)算符右
側(cè)指定的位數(shù)。
“有符號(hào)”右移位運(yùn)算符使用了“符號(hào)擴(kuò)展”:若值為正,則在高位插入0;若
值為負(fù),則在高位插入1。
3)Java也添加了一種“無符號(hào)”右移位運(yùn)算符(>>>),它使用了“零擴(kuò)展”:
無論正負(fù),都在高位插入0。這一運(yùn)算符是C或C++沒有的。
4)若對(duì)char,byte或者short進(jìn)行移位處理,那么在移位進(jìn)行之前,它們會(huì)自
動(dòng)轉(zhuǎn)換成一個(gè)int。
只有右側(cè)的5個(gè)低位才會(huì)用到。這樣可防止我們?cè)谝粋€(gè)int數(shù)里移動(dòng)不切實(shí)際的
位數(shù)。
若對(duì)一個(gè)long值進(jìn)行處理,最后得到的結(jié)果也是long。此時(shí)只會(huì)用到右側(cè)的6
個(gè)低位,防止移動(dòng)超過long值里現(xiàn)成的位數(shù)。
但在進(jìn)行“無符號(hào)”右移位時(shí),也可能遇到一個(gè)問題。若對(duì)byte或short值進(jìn)
行右移位運(yùn)算,得到的可能不是正確的結(jié)果(Java1.0和Java1.1特別突出)。
它們會(huì)自動(dòng)轉(zhuǎn)換成int類型,并進(jìn)行右移位。但“零擴(kuò)展”不會(huì)發(fā)生,所以在那
些情況下會(huì)得到-1的結(jié)果。
在進(jìn)行位運(yùn)算時(shí),需要注意以下幾點(diǎn)。
(1)>>>和〉的區(qū)別是:在執(zhí)行運(yùn)算時(shí),>>>運(yùn)算符的操作數(shù)高位補(bǔ)0,而>>運(yùn)算
符的操作數(shù)高位移入原來高位的值。
⑵右移一位相當(dāng)于除以2,左移一位(在不溢出的情況下)相當(dāng)于乘以2;移位運(yùn)
算速度高于乘除運(yùn)算。
(3)若進(jìn)行位邏輯運(yùn)算的兩個(gè)操作數(shù)的數(shù)據(jù)長(zhǎng)度不相同,則返回值應(yīng)該是數(shù)據(jù)長(zhǎng)
度較長(zhǎng)的數(shù)據(jù)類型。
(4)按位異或可以不使用臨時(shí)變量完成兩個(gè)值的交換,也可以使某個(gè)整型數(shù)的特
定位的值翻轉(zhuǎn)。
(5)按位與運(yùn)算可以用來屏蔽特定的位,也可以用來取某個(gè)數(shù)型數(shù)中某些特定的
位。
⑹按位或運(yùn)算可以用來對(duì)某個(gè)整型數(shù)的特定位的值置lo
3.位運(yùn)算符的優(yōu)先級(jí)
~的優(yōu)先級(jí)最高,其次是《、>>和>>>,再次是&,然后是"優(yōu)先級(jí)最低的是|。
二,按位異或運(yùn)算符”
參與運(yùn)算的兩個(gè)值,如果兩個(gè)相應(yīng)位相同,則結(jié)果為0,否則為1。即:0^0=0,
1^0=1,0^1=1,1^1=0
例如:ioiooooroooioooi=ionoooo
0^0=0,0^1=10異或任何數(shù)=任何數(shù)
ro=i,ri=oi異或任何數(shù)一任何數(shù)取反
任何數(shù)異或自己=把自己置o
(1)按位異或可以用來使某些特定的位翻轉(zhuǎn),如對(duì)數(shù)10100001的第2位和第3
位翻轉(zhuǎn),可以將數(shù)與00000110進(jìn)行按位異或運(yùn)算。
1010000r00000110=10100111//10100001八0x06=1010
0001-6
(2)通過按位異或運(yùn)算,可以實(shí)現(xiàn)兩個(gè)值的交換,而不必使用臨時(shí)變量。例如交
換兩個(gè)整數(shù)a,b的值,可通過下列語句實(shí)現(xiàn):
a=10100001,b=00000110
a=a^b;//a=10100111
b=b^a;//b=10100001
a=a"b;//a=00000110
(3)異或運(yùn)算符的特點(diǎn)是:數(shù)a兩次異或同一個(gè)數(shù)b(a=個(gè)b'b)仍然為原值a.
三,Java中除了二進(jìn)制的表示方法:
由于數(shù)據(jù)在計(jì)算機(jī)中的表示,最終以二進(jìn)制的形式存在,所以有時(shí)候使用二進(jìn)制,
可以更直觀地解決問題。
但,二進(jìn)制數(shù)太長(zhǎng)了。比如int類型占用4個(gè)字節(jié),32位。比如100,用
int類型的二進(jìn)制數(shù)表達(dá)將是:
000000000000000001100100
面對(duì)這么長(zhǎng)的數(shù)進(jìn)行思考或操作,沒有人會(huì)喜歡。因此,C,C++,以及java
中沒有提供在代碼直接寫二進(jìn)制數(shù)的方法。
八進(jìn)制數(shù)的表達(dá)方法
如何表達(dá)一個(gè)八進(jìn)制數(shù)呢?如果這個(gè)數(shù)是876,我們可以斷定它不是八進(jìn)制
數(shù),因?yàn)榘诉M(jìn)制數(shù)中不可能出7以上的阿拉伯?dāng)?shù)字。但如果這個(gè)數(shù)是123、是567,
或12345670,那么它是八進(jìn)制數(shù)還是八進(jìn)制數(shù),都有可能。
所以規(guī)定,一個(gè)數(shù)如果要指明它采用八進(jìn)制,必須在它前面加上一個(gè)0,如:123
是十進(jìn)制,但0123則表示采用八進(jìn)制。這就是八進(jìn)制數(shù)的表達(dá)方法。
現(xiàn)在,對(duì)于同樣一個(gè)數(shù),比如是100,我們?cè)诖a中可以用平常的10進(jìn)制表達(dá),
例如在變量初始化時(shí):
inta=100;
我們也可以這樣寫:
inta=0144;〃0144是八進(jìn)制的100;一個(gè)10進(jìn)制數(shù)如何
轉(zhuǎn)成8進(jìn)制。
千萬記住,用八進(jìn)制表達(dá)時(shí),你不能少了最前的那個(gè)0。否則計(jì)算機(jī)會(huì)通通當(dāng)成
10進(jìn)制。不過,有一個(gè)地方使用八進(jìn)制數(shù)時(shí),卻不能使用加0,那就是我們前面
學(xué)的用于表達(dá)字符的“轉(zhuǎn)義符”表達(dá)法。
十六進(jìn)制數(shù)的表達(dá)方法
如果不使用特殊的書寫形式,16進(jìn)制數(shù)也會(huì)和10進(jìn)制相混。隨便一個(gè)數(shù):9876,
就看不出它是16進(jìn)制或10進(jìn)制。
16進(jìn)制數(shù)必須以O(shè)x開頭。比如0x1表示一個(gè)16進(jìn)制數(shù)。而1則表示
一個(gè)十進(jìn)制。另外如:Oxff,OxFF,0X102A,等等。其中的x也也不區(qū)分大小寫.(注
意:Ox中的0是數(shù)字0,而不是字母0)
以下是一些用法示例:
inta=OxlOOF;
intb=0x70+a;
最后一點(diǎn)很重要,10進(jìn)制數(shù)有正負(fù)之分,比如12表示正12,而T2表示負(fù)12,;
但8進(jìn)制和16進(jìn)制只能用達(dá)無符號(hào)的正整數(shù),如果你在代碼中里:-078,或者
寫:-0xF2,編譯器并不把它當(dāng)成一個(gè)負(fù)數(shù)。
/*位運(yùn)算
*java使用補(bǔ)碼來表示2進(jìn)制數(shù),最高位為符號(hào)位,正數(shù)為0,負(fù)數(shù)為1,補(bǔ)碼規(guī)定:
*整數(shù),最高位是0,其余是本身,如+42的補(bǔ)碼為00101010
*負(fù)數(shù),最高位是1,將其余的決定值按位取反,最后+1,即為負(fù)數(shù)的補(bǔ)碼;
*如-42的補(bǔ)碼為11010110(00101010按位取反11010101
+1=11010110)
si*
,,、rj**Jw,,、
*邏輯運(yùn)算*
?£?*£*?£??X**1*
*i**7**7、*i?,]、,[、*7**,?
a&b與門[真真為真,真假為假]
00000000000000000000000000000001
00000000000000000000000000000010
00000000000000000000000000000000
System,out.printin(1&2);
結(jié)果為0
a|b或門[假假為假,其余全真]
00000000000000000000000000000001
00000000000000000000000000000010
00000000000000000000000000000011
System.out.println(12);
結(jié)果為3
~a非門[真則假,假則真]
00000000000000000000000000000001
11111111111111111111111111111110
System.out.printIn("1);
結(jié)果為:—2
a'b異或門:[相同為假,不同為真]
00000000000000000000000000000001
00000000000000000000000000000010
00000000000000000000000000000011
System.out.printin(/2);
結(jié)果為3
*T*
*移位運(yùn)算*
*1**1**1*
a>>b有符號(hào)右移位;將a右移b位;若正數(shù),高位補(bǔ)0,負(fù)數(shù),高位補(bǔ)1
00000000000000000000000000000011
?1
00000000000000000000000000000001
System.out.printin(3>>1);
結(jié)果為1,結(jié)果與3/2的1次基相同
a?b有符號(hào)左移位;將a左移b位,若正數(shù),高位補(bǔ)0,負(fù)數(shù),高位補(bǔ)1
00000000000000000000000000000011
?2
00000000000000000000000000001100
System.out.printin(3?2);
結(jié)果為12,與3*2的2次第相同
a?>b無符號(hào)右移位;將a左移b位,不論正負(fù),高位均補(bǔ)0
00000000000000000000000000000011
?1
00000000000000000000000000000001
System.out.printIn(3?>1);
結(jié)果為1,與3/2的1次幕相同
*/
System.out.printin(3?>1);
System.out.printin(i;
Java定義的位運(yùn)算(bitwiseoperators)直接對(duì)整數(shù)類型的位進(jìn)行操作,這
些整數(shù)類型包括long,int,short,char,andbyte。
運(yùn)算符結(jié)果
~按位非(NOT)(一元運(yùn)算)
&按位與(AND)
I按位或(OR)
“按位異或(XOR)
〉〉右移
?>右移,左邊空出的位以。填充
運(yùn)算符結(jié)果
?左移
&-按位與賦值
1=按位或賦值
J按位異或賦值
?=右移賦值
?>=右移賦值,左邊空出的位以0填充
?=左移賦值
既然位運(yùn)算符在整數(shù)范圍內(nèi)對(duì)位操作,因此理解這樣的操作會(huì)對(duì)一個(gè)值產(chǎn)生什么
效果是重要的。具體坦說,知道Java是如何存儲(chǔ)整數(shù)值并且如何表示負(fù)數(shù)的是
有用的。因此,在繼續(xù)討論之前,讓我們簡(jiǎn)短概述一下這兩個(gè)話題。
所有的整數(shù)類型以二進(jìn)制數(shù)字位的變化及其寬度來表示。例如,byte型值42
的二進(jìn)制代碼是00101010,其中每個(gè)位置在此代表2的次方,在最右邊的位以
20開始。向左下一個(gè)位置將是21,或2,依次向左是22,或4,然后是8,16,
32等等,依此類推。因此42在其位置1,3,5的值為1(從右邊以0開始數(shù));
這樣42是21十23+25的和,也即是2+8+32。
所有的整數(shù)類型(除了char類型之外)都是有符號(hào)的整數(shù)。這意味著他們既
能表示正數(shù),又能表示負(fù)數(shù)。Java使用大家知道的2的補(bǔ)碼(two,s
complement)這種編碼來表示負(fù)數(shù),也就是通過將與其對(duì)應(yīng)的正數(shù)的二進(jìn)制代
碼取反(即將1變成0,將0變成1),然后對(duì)其結(jié)果加1。例如,-42就是通過
將42的二進(jìn)制代碼的各個(gè)位取反,即對(duì)00101010取反得到11010101,然后
再加1,得到11010110,BP-42。要對(duì)一個(gè)負(fù)數(shù)解碼,首先對(duì)其所有的位取反,
然后加1。例如-42,或11010110取反后為00101001,或41,然后加1,這樣
就得到了42。
如果考慮到零的交叉(zerocrossing)問題,你就容易理解Java(以及其他
絕大多數(shù)語言)這樣用2的補(bǔ)碼的原因。假定byte類型的值冬用00000000代
表。它的補(bǔ)碼是僅僅將它的每一位取反,即生成11111111,它代表負(fù)零。但問
題是負(fù)零在整數(shù)數(shù)學(xué)中是無效的。為了解決負(fù)零的問題,在使用2的補(bǔ)碼代表負(fù)
數(shù)的值時(shí),對(duì)其值加lo即負(fù)零11111111加1后為100000000o但這樣使1位
太靠左而不適合返回到byte類型的值,因此人們規(guī)定,-0和0的表示方法一樣,
7的解碼為11111111。盡管我們?cè)谶@個(gè)例子使用了byte類型的值,但同樣的
基本的原則也適用于所有Java的整數(shù)類型。
因?yàn)镴ava使用2的補(bǔ)碼來存儲(chǔ)負(fù)數(shù),并且因?yàn)镴ava中的所有整數(shù)都是有符號(hào)
的,這樣應(yīng)用位運(yùn)算符可以容易地達(dá)到意想不到的結(jié)果。例如,不管你如何打算,
Java用高位來代表負(fù)數(shù)。為避免這個(gè)討厭的意外,請(qǐng)記住不管高位的順序如何,
它決定一個(gè)整數(shù)的符號(hào)。
4.2.1位邏輯運(yùn)算符
位邏輯運(yùn)算符有“與"(AND)、“或"(0R)、“異或(XOR)”、“非(NOT)”,
分別用“&”、「”、?”、…表示,4-3表顯示了每個(gè)位邏輯運(yùn)算的結(jié)果。
在繼續(xù)討論之前,請(qǐng)記住位運(yùn)算符應(yīng)用于每個(gè)運(yùn)算數(shù)內(nèi)的每個(gè)單獨(dú)的位。
表4-3位邏輯運(yùn)算符的結(jié)果
A0101B0011A|B0111A&B0001A"B0110"A101
0
按位非(NOT)
按位非也叫做補(bǔ),一元運(yùn)算符NOT是對(duì)其運(yùn)算數(shù)的每一位取反。例如,數(shù)
字42,它的二進(jìn)制代碼為:
00101010
經(jīng)過按位非運(yùn)算成為
11010101
按位與(AND)
按位與運(yùn)算符“&”,如果兩個(gè)運(yùn)算數(shù)都是1,則結(jié)果為1。其他情況下,結(jié)果均
為零??聪旅娴睦樱?/p>
0010101042&0000111115
0000101010
按位或(OR)
按位或運(yùn)算符“I”,任何一個(gè)運(yùn)算數(shù)為1,則結(jié)果為1。如下面的例子所示:
0010101042|0000111115
0010111147
按位異或(XOR)
按位異或運(yùn)算符“一",只有在兩個(gè)比較的位不同時(shí)其結(jié)果是k否則,結(jié)果是
零。下面的例子顯示了“一’運(yùn)算符的效果。這個(gè)例子也表明了XOR運(yùn)算符的一
個(gè)有用的屬性。注意第二個(gè)運(yùn)算數(shù)有數(shù)字1的位,42對(duì)應(yīng)二進(jìn)制代碼的對(duì)應(yīng)位
是如何被轉(zhuǎn)換的。第二個(gè)運(yùn)算數(shù)有數(shù)字0的位,第一個(gè)運(yùn)算數(shù)對(duì)應(yīng)位的數(shù)字不
變。當(dāng)對(duì)某些類型進(jìn)行位運(yùn)算時(shí),你將會(huì)看到這個(gè)屬性的用處。
0010101042,0000111115
0010010137
位邏輯運(yùn)算符的應(yīng)用
下面的例子說明了位邏輯運(yùn)算符:
//Demonstratethebitwiselogicaloperators.
classBitLogic{
publicstaticvoidnain(Stringargs[]){
Stringbinary[]={〃0000〃,〃0001〃,〃0010〃,〃0100〃,〃0110〃,
〃oiu〃,〃iooo〃,〃iou〃,〃noo〃,
};
inta=3;//0+2+1or0011inbinary
intb=6;//4+2+0or0110inbinary
intc=a|b;
intd=a&b;
inte=ab;
intf=(~a&b)|ia&~b);
intg=~a&OxOf;
System.out.printIn(*a="+binary[a]);
System.out.printinC'b=〃+binary);
System.out.printIna|b=〃+binary[c]);
System,out.printinCa&b=〃+binary[d]);
System.out.printinCab=〃+binary[e]);
System.out.printin("~a&b|a&~b=〃+binary[f]);
System.out.printin(*=〃+binary[g]);
)
)
在本例中,變量a與b對(duì)應(yīng)位的組合代表了二進(jìn)制數(shù)所有的4種組合模式:0-0,
0-1,1-0,和1-1。運(yùn)算符和運(yùn)算符分別對(duì)變量a與b各個(gè)對(duì)應(yīng)位
的運(yùn)算得到了變量c和變量d的值。對(duì)變量e和f的賦值說明了運(yùn)算符的
功能。字符串?dāng)?shù)組binary代表了0到15對(duì)應(yīng)的二進(jìn)制的值。在本例中,數(shù)組
各元素的排列順序顯示了變量對(duì)應(yīng)值的二進(jìn)制代碼。數(shù)組之所以這樣構(gòu)造是因?yàn)?/p>
變量的值n對(duì)應(yīng)的二進(jìn)制代碼可以被正確的存儲(chǔ)在數(shù)組對(duì)應(yīng)元素binary[n]
中。例如變量a的值為3,則它的二進(jìn)制代碼對(duì)應(yīng)地存儲(chǔ)在數(shù)組元素binab[3]
中。%的值與數(shù)字OxOf(對(duì)應(yīng)二進(jìn)制為00001111)進(jìn)行按位與運(yùn)算的目的
是減?。サ闹?,保證變量g的結(jié)果小于16。因此該程序的運(yùn)行結(jié)果可以用數(shù)組
binary對(duì)應(yīng)的元素來表示。該程序的輸出如下:
a=0011b=0110a|b=0111a&b=0010a^b=0101?a&b|a&~b=0101
=1100
4.2.2左移運(yùn)算符
左移運(yùn)算符《使指定值的所有位都左移規(guī)定的次數(shù)。它的通用格式如下所示:
value<<num
這里,num指定要移位值value移動(dòng)的位數(shù)。也就是,左移運(yùn)算符<〈使指定值
的所有位都左移num位。每左移一個(gè)位,高階位都被移出(并且丟棄),并用0
填充右邊。這意味著當(dāng)左移的運(yùn)算數(shù)是int類型時(shí),每移動(dòng)1位它的第3:位
就要被移出并且丟棄;當(dāng)左移的運(yùn)算數(shù)是long類型時(shí),每移動(dòng)1位它的第63
位就要被移出并且丟棄。
在對(duì)byte和short類型的值進(jìn)行移位運(yùn)算時(shí),你必須小心。因?yàn)槟阒繨ava在
對(duì)表達(dá)式求值時(shí),將自動(dòng)把這些類型擴(kuò)大為int型,而且,表達(dá)式的值也是int
型。對(duì)byte和short類型的值進(jìn)行移位運(yùn)算的結(jié)果是int型,而且如果左移不
超過31位,原來對(duì)應(yīng)各位的值也不會(huì)丟棄。但是,如果你對(duì)一個(gè)負(fù)的byle或
者short類型的值進(jìn)行移位運(yùn)算,它被擴(kuò)大為int型后,它的符號(hào)也被擴(kuò)展。
這樣,整數(shù)值結(jié)果的高位就會(huì)被1填充。因此,為了得到正確的結(jié)果,你就要舍
棄得到結(jié)果的高位。這樣做的最簡(jiǎn)單辦法是將結(jié)果轉(zhuǎn)換為byte型。下面的程序
說明了這一點(diǎn):
//Leftshiftingabytevalue.
classByteShift{
publicstaticvoidnain(Stringargs[]){
bytea=64,b;
inti;
i=a?2;
b=(byte)(a<<2):
System.out.printin(^Originalvalueofa:〃+a);
System.out.printIn(^iandb:〃+i+〃〃+b);
)
)
該程序產(chǎn)生的輸出下所示:
Originalvalueofa:64
iandb:2560
因變量a在賦值表達(dá)式中,故被擴(kuò)大為int型,64(01000000)被左移兩次
生成值256(100000000)被賦給變量i。然而,經(jīng)過左移后,變量b中惟一
的1被移出,低位全部成了0,因此b的值也變成了0。
既然每次左移都可以使原來的操作數(shù)翻倍,程序員們經(jīng)常使用這個(gè)辦法來進(jìn)行快
速的2的乘法。但是你要小心,如果你將1移進(jìn)高階位(31或63位),那么該
值將變?yōu)樨?fù)值。下面的程序說明了這一點(diǎn):
//Leftshiftingasaquickwaytomultiplyby2.
classMuItByTwo{
publicstaticvoidnain(Stringargs[]){
inti;
intnum=OxFFFFFFE:
for(i=0;i<4;i++)(
num=num<<1;
System.out.printin(num);
)
}
這num指定要移位值value移動(dòng)的位數(shù)。也就是,左移運(yùn)算符《使指定值
的所有位都左移num位。每左移一個(gè)位,高階位都被移出(并且丟棄),并用0
填充右邊。這意味著當(dāng)左移的運(yùn)算數(shù)是int類型時(shí),每移動(dòng)1位它的第3:位
就要被移出并且丟棄;當(dāng)左移的運(yùn)算數(shù)是long類型時(shí),每移動(dòng)1位它的第63
位就要被移出并且丟棄。
在對(duì)byte和short類型的值進(jìn)行移位運(yùn)算時(shí),你必須小心。因?yàn)槟阒繨ava在
對(duì)表達(dá)式求值時(shí),將自動(dòng)把這些類型擴(kuò)大為int型,而且,表達(dá)式的值也是int
型。對(duì)byte和short類型的值進(jìn)行移位運(yùn)算的結(jié)果是ini型,而且如果左移不
超過31位,原來對(duì)應(yīng)各位的值也不會(huì)丟棄。但是,如果你對(duì)一個(gè)負(fù)的byte或
者short類型的值進(jìn)行移位運(yùn)算,它被擴(kuò)大為int型后,它的符號(hào)也被擴(kuò)展。
這樣,整數(shù)值結(jié)果的高位就會(huì)被1填充。因此,為了得到正確的結(jié)果,你就要舍
棄得到結(jié)果的高位。這樣做的最簡(jiǎn)單辦法是將結(jié)果轉(zhuǎn)換為byte型。下面的程序
說明了這一點(diǎn):
//Leftshiftingabytevalue.
classByteShift{
publicstaticvoidnain(Stringargs[]){
bytea=64,b;
inti;
i=a?2;
b=(byte)(a<<2);
System,out.printin(^Originalvalueofa:〃+a);
System.out.printinandb:"+i+"〃+b);
)
)
該程序產(chǎn)生的輸出下所示:
Originalvalueofa:64
iandb:2560
因變量a在賦值表達(dá)式中,故被擴(kuò)大為int型,64(01000000)被左移兩次
生成值256(100000000)被賦給變量i。然而,經(jīng)過左移后,變量b中惟一
的1被移出,低位全部成了0,因此b的值也變成了0。
既然每次左移都可以使原來的操作數(shù)翻倍,程序員們經(jīng)常使用這個(gè)辦法來進(jìn)行快
速的2的乘法。但是你要小心,如果你將1移進(jìn)高階位(31或63位),那么該
值將變?yōu)樨?fù)值。下面的程序說明了這一點(diǎn):
//Leftshiftingasaquickwaytomultiplyby2.
classMuItByTwo{
publicstaticvoidnain(Stringargs[]){
inti;
intnum=OxFFFFFFE:
for(i=0;i<4;i++)(
num=num<<1;
System.out.printin(num);
)
)
)
該程序的輸出如下所示:
536870908
1073741816
2147483632
-32
初值經(jīng)過仔細(xì)選擇,以便在左移4位后,它會(huì)產(chǎn)生-32。正如你看到的,當(dāng)1
被移進(jìn)31位時(shí),數(shù)字被解釋為負(fù)值。
4.2.3右移運(yùn)算符
右移運(yùn)算符》使指定值的所有位都右移規(guī)定的次數(shù)。它的通用格式如下所示:
value>>num
這里,num指定要移位值value移動(dòng)的位數(shù)。也就是,右移運(yùn)算符*使指定值
的所有位都右移num位。下面的程序片段將值32右移2次,將結(jié)果8賦給變量
a:
inta=32;
a=a>>2;//anowcontains8
當(dāng)值中的某些位被“移出”時(shí),這些位的值將丟棄。例如,下面的程序片段將
35右移2次,它的2個(gè)低位被移出丟棄,也將結(jié)果8賦給變量a:
inta=35;
a=a?2;//astillcontains8
用二進(jìn)制表示該過程兀以更清楚地看到程序的運(yùn)行過程:
0010001135
?2
000010008
將值每右移一次,就相當(dāng)于將該值除以2并且舍棄了余數(shù)。你可以利用這個(gè)特點(diǎn)
將一個(gè)整數(shù)進(jìn)行快速的2的除法。當(dāng)然,你一定要確保你不會(huì)將該數(shù)原有的任何
一位移出。
右移時(shí),被移走的最高位(最左邊的位)由原來最高位的數(shù)字補(bǔ)充。例如,如
果要移走的值為負(fù)數(shù),每一次右移都在左邊補(bǔ)1,如果要移走的值為正數(shù),每一
次右移都在左邊補(bǔ)0,這叫做符號(hào)位擴(kuò)展(保留符號(hào)位)(signext6nsion),
在進(jìn)行右移操作時(shí)用來保持負(fù)數(shù)的符號(hào)。例如,-8>>1是-4,用二進(jìn)制表示
如下:
11111000-8?111111100-4
一個(gè)要注意的有趣問題是,由于符號(hào)位擴(kuò)展(保留符號(hào)位)每次都會(huì)在高位補(bǔ)1,
因此T右移的結(jié)果總是-1。有時(shí)你不希望在右移時(shí)保留符號(hào)。例如,下面的例
子將一個(gè)byte型的值轉(zhuǎn)換為用十六
進(jìn)制表示。注意右移后的值與OxOf進(jìn)行按位與運(yùn)算,這樣可以舍棄任何的符號(hào)
位擴(kuò)展,以便得到的值可以作為定義數(shù)組的下標(biāo),從而得到對(duì)應(yīng)數(shù)組元素代表的
十六進(jìn)制字符。
//Maskingsignextension.
classHexByte{
staticpublicvoidnain(Stringargs[]){
charhex[]={
'8','9','a','b','c','d','e','f''
};
byteb=(byte)Oxfl;
System,out.printin(^b=0x〃+hex[(b>>4)&OxOf]+hex[b&OxOf]);J)
該程序的輸出如下:
b=Oxfl
4.2.4無符號(hào)右移
正如上面剛剛看到的,每一次右移,>>運(yùn)算符總是自動(dòng)地用它的先前最高位的
內(nèi)容補(bǔ)它的最高位。這樣做保留了原值的符號(hào)。但有時(shí)這并不是我們想要的。
例如,如果你進(jìn)行移位操作的運(yùn)算數(shù)不是數(shù)字值,你就不希望進(jìn)行符號(hào)位擴(kuò)展(保
留符號(hào)位)。當(dāng)你處理像素值或圖形時(shí),這種情況是相當(dāng)普遍的。在這種情況下,
不管運(yùn)算數(shù)的初值是什么,你希望移位后總是在高位(最左邊)補(bǔ)0。這就是人
們所說的無符號(hào)移動(dòng)(unsignedshift)<>這時(shí)你可以使用Java的無符號(hào)右
移運(yùn)算符>>>,它總是在左邊補(bǔ)0。
下面的程序段說明了無符號(hào)右移運(yùn)算符>〉>o在本例中,變量a被賦值為T,用
二進(jìn)制表示就是32位全是1。這個(gè)值然后被無符號(hào)右移24位,當(dāng)然它忽略了符
號(hào)位擴(kuò)展,在它的左邊總是補(bǔ)0。這樣得到的值255被賦給變量a。
inta=-1;a=a>?24;
下面用二進(jìn)制形式進(jìn)一步說明該操作:
11111111111111111111111111111111int型T的二進(jìn)制代碼>>>24無符號(hào)
右移24位00000000000000000000000011111111int型255的二進(jìn)制代碼
由于無符號(hào)右移運(yùn)算符>>>只是對(duì)32位和64位的值有意義,所以它并不像你
想象的那樣有用。因?yàn)槟阋涀?,在表達(dá)式中過小的值總是被自動(dòng)擴(kuò)大為int
型。這意味著符號(hào)位擴(kuò)展和移動(dòng)總是發(fā)生在32位而不是8位或16位。這樣,對(duì)
第7位以0開始的byte型的值進(jìn)行無符號(hào)移動(dòng)是不可能的,因?yàn)樵趯?shí)際移動(dòng)運(yùn)
算時(shí),是對(duì)擴(kuò)大后的32位值進(jìn)行操作。下面的例子說明了這一點(diǎn):
//Unsignedshiftingabytevalue.
classByteUShift{
staticpublicvoidnain(Stringargs[]){
進(jìn)制表示。注意右移后的值與OxOf進(jìn)行按位與運(yùn)算,這樣可以舍棄任何的符號(hào)
位擴(kuò)展,以便得到的值可以作為定義數(shù)組的下標(biāo),從而得到對(duì)應(yīng)數(shù)組元素代表的
十六進(jìn)制字符。
//Maskingsignextension.
classHexByte{
staticpublicvoidnain(Stringargs[]){
charhex[]=(
'8','9','a','b','c','d','e','f''
};
byteb=(byte)Oxfl;
System,out.printin(*b=0x〃+hex[(b?4)&OxOf]+hex[b&OxOf]);}}
該程序的輸出如下:
b=Oxfl
4.2.4無符號(hào)右移
正如上面剛剛看到的,每一次右移,*運(yùn)算符總是自動(dòng)地用它的先前最高位的
內(nèi)容補(bǔ)它的最高位。這樣做保留了原值的符號(hào)。但有時(shí)這并不是我們想要的。
例如,如果你進(jìn)行移位噪作的運(yùn)算數(shù)不是數(shù)字值,你就不希望進(jìn)行符號(hào)位擴(kuò)展(保
留符號(hào)位)。當(dāng)你處理像素值或圖形時(shí),這種情況是相當(dāng)普遍的。在這種情況下,
不管運(yùn)算數(shù)的初值是什么,你希望移位后總是在高位(最左邊)補(bǔ)0。這就是人
們所說的無符號(hào)移動(dòng)(unsignedshift)。這時(shí)你可以使用Java的無符號(hào)右
移運(yùn)算符>>>,它總是在左邊補(bǔ)0。
下面的程序段說明了無符號(hào)右移運(yùn)算符>〉>o在本例中,變量a被賦值為-1,用
二進(jìn)制表示就是32位全是1。這個(gè)值然后被無符號(hào)右移24位,當(dāng)然它忽略了符
號(hào)位擴(kuò)展,在它的左邊總是補(bǔ)0。這樣得到的值255被賦給變量a。
inta=-1;a=a?>24;
下面用二進(jìn)制形式進(jìn)一步說明該操作:
11111111111111111111111111111111int型-1的二進(jìn)制代碼>>>24無符號(hào)
右移24位00000000000000000000000011111111int型255的二進(jìn)制代碼
由于無符號(hào)右移運(yùn)算符只是對(duì)32位和64位的值有意義,所以它并不像你
想象的那樣有用。因?yàn)槟阋涀。诒磉_(dá)式中過小的值總是被自動(dòng)擴(kuò)大為int
型。這意味著符號(hào)位擴(kuò)展和移動(dòng)總是發(fā)生在32位而不是8位或16位。這樣,對(duì)
第7位以0開始的byte型的值進(jìn)行無符號(hào)移動(dòng)是不可能的,因?yàn)樵趯?shí)際移動(dòng)運(yùn)
算時(shí),是對(duì)擴(kuò)大后的32位值進(jìn)行操作。下面的例子說明了這一點(diǎn):
//Unsignedshiftingabytevalue.
classByteUShift{
staticpublicvoidnain(Stringargs[]){
intb=2;
intc=3;
a|=4;
b?=1;
c?=1;
a-=c;
System.out.printin(*a=〃+a);
System.out.printin(*b=〃+b);
System.out.printin(*c="+c);
)
)
該程序的輸出如下所示:
a=3
b=1
C=6附錄資料:
java處理高并發(fā)高負(fù)載類網(wǎng)站的優(yōu)化方法
java處理高并發(fā)高負(fù)載類網(wǎng)站中數(shù)據(jù)庫(kù)的設(shè)計(jì)方法(java教程Java處理大量數(shù)
據(jù),java高負(fù)載數(shù)據(jù))
-:高并發(fā)高負(fù)載類網(wǎng)站關(guān)注點(diǎn)之?dāng)?shù)據(jù)庫(kù)
沒錯(cuò),首先是數(shù)據(jù)庫(kù),這是大多數(shù)應(yīng)用所面臨的首個(gè)SPOF。尤其是Web2.0的應(yīng)
用,數(shù)據(jù)庫(kù)的響應(yīng)是首先要解決的。一般來說MySQL是最常用的,可能最初是
一個(gè)mysql主機(jī),當(dāng)數(shù)據(jù)增加到100萬以上,那么,MySQL的效能急劇下降。
常用的優(yōu)化措施是M-S(主-從)方式進(jìn)行同步復(fù)制,將查詢和操作和分別在不
同的服務(wù)器上進(jìn)行操作。我推薦的是M-M-Slaves方式,2個(gè)主Mysql,多個(gè)
Slaves,需要注意的是,雖然有2個(gè)Master,但是同時(shí)只有1個(gè)是Active,我
們可以在一定時(shí)候切換。之所以用2個(gè)M,是保證M不會(huì)又成為系統(tǒng)的SPOF。
Slaves可以進(jìn)一步負(fù)載均衡,可以結(jié)合LVS,從而將select操作適當(dāng)?shù)钠胶獾讲?/p>
同的slaves上。以上架構(gòu)可以抗衡到一定量的負(fù)載,但是隨著用戶進(jìn)一步增加,
你的用戶表數(shù)據(jù)超過1千萬這時(shí)那個(gè)M變成了SPOF。你不能任意擴(kuò)充Slaves,
否則復(fù)制同步的開銷將直線上升,怎么辦?我的方法是表分區(qū),從業(yè)務(wù)層面上進(jìn)
行分區(qū)。最簡(jiǎn)單的,以用戶數(shù)據(jù)為例。根據(jù)一定的切分方式,比如id,切分到
不同的數(shù)據(jù)庫(kù)集群去。
全局?jǐn)?shù)據(jù)庫(kù)用于meta數(shù)據(jù)的查詢。缺點(diǎn)是每次查詢,會(huì)增加一次,比如你要查
一個(gè)用戶nightsailer,你首先要到全局?jǐn)?shù)據(jù)庫(kù)群找到nightsailer對(duì)應(yīng)的cluster
id,然后再到指定的cluster找至I」nightsailer的實(shí)際數(shù)據(jù)。每個(gè)cluster可以用
m-m方式,或者m-m-slaves方式。這是一個(gè)可以擴(kuò)展的結(jié)構(gòu),隨著負(fù)載的增
加,你可以簡(jiǎn)單的增加新的mysqlcluster進(jìn)去。
需要注意的是:1、禁用全部auto_increment的字段2、id需要采用通用的算
法集中分配3、要具有比較好的方法來監(jiān)控mysql主機(jī)的負(fù)載和服務(wù)的運(yùn)行狀
態(tài)。如果你有30臺(tái)以上的mysql數(shù)據(jù)庫(kù)在跑就明白我的意思了。4、不要使用
持久性鏈接(不要用pconnect)相反,使用sqlrelay這種第三方的數(shù)據(jù)庫(kù)鏈接
池,或者干脆自己做,因?yàn)閜hp4中mysql的鏈接池經(jīng)常出問題。二:高并發(fā)
高負(fù)載網(wǎng)站的系統(tǒng)架構(gòu)之HTML靜態(tài)化
其實(shí)大家都知道,效率最高、消耗最小的就是純靜態(tài)化,所以我們盡可能使我們
的網(wǎng)站上的頁面采用靜態(tài)頁面來實(shí)現(xiàn),這個(gè)最簡(jiǎn)單的方法其實(shí)也是最有效的方
法。但是對(duì)于大量?jī)?nèi)容并且頻繁更新的網(wǎng)站,我們無法全部手動(dòng)去挨個(gè)實(shí)現(xiàn),于
是出現(xiàn)了我們常見的信息發(fā)布系統(tǒng)CMS,像我們常訪問的各個(gè)門戶站點(diǎn)的新聞
頻道,甚至他們的其他頻道,都是通過信息發(fā)布系統(tǒng)來管理和實(shí)現(xiàn)的,信息發(fā)布
系統(tǒng)可以實(shí)現(xiàn)最簡(jiǎn)單的信息錄入自動(dòng)生成靜態(tài)頁面,還能具備頻道管理、權(quán)限管
理、自動(dòng)抓取等功能,對(duì)于一個(gè)大型網(wǎng)站來說,擁有一套高效、可管理的CMS
是必不可少的。除了門戶和信息發(fā)布類型的網(wǎng)站,對(duì)于交互性要求很高的社
區(qū)類型網(wǎng)站來說,盡可能的靜態(tài)化也是提高性能的必要手段,將社區(qū)內(nèi)的帖子、
文章進(jìn)行實(shí)時(shí)的靜態(tài)化,有更新的時(shí)候再重新靜態(tài)化也是大量使用的策略,像
Mop的大雜燒就是使用了這樣的策略,網(wǎng)易社區(qū)等也是如此。同時(shí),html
靜態(tài)化也是某些緩存策略使用的手段,對(duì)于系統(tǒng)中頻繁使用數(shù)據(jù)庫(kù)查詢但是內(nèi)容
更新很小的應(yīng)用,可以考慮使用html靜態(tài)化來實(shí)現(xiàn),比如論壇中論壇的公用
設(shè)置信息,這些信息目前的主流論壇都可以進(jìn)行后臺(tái)管理并且存儲(chǔ)再數(shù)據(jù)庫(kù)中,
這些信息其實(shí)大量被前臺(tái)程序調(diào)用,但是更新頻率很小,可以考慮將這部分內(nèi)
容進(jìn)行后臺(tái)更新的時(shí)候進(jìn)行靜態(tài)化,這樣避免了大量的數(shù)據(jù)庫(kù)訪問請(qǐng)求高并發(fā)。
網(wǎng)站HTML靜態(tài)化解戾方案當(dāng)一個(gè)Servlet資源清求到達(dá)WEB服務(wù)器之后我們
會(huì)填充指定的JSP頁面來響應(yīng)請(qǐng)求:
HTTP請(qǐng)求Web服務(wù)器-Servlet一業(yè)務(wù)邏輯處理--訪問數(shù)據(jù)--填充JSP--響
應(yīng)請(qǐng)求
HTML靜態(tài)化之后:
HTTP請(qǐng)求???Web月艮務(wù)器Servlet--HTML--響應(yīng)請(qǐng)求
靜態(tài)訪求如下
Servlet:
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponse
response)throwsServletException,lOException
{if(request.getParameter("chapterIdn)!=null){String
chapterFileName=
nbookChapterRead_'+request.getRarameter("chapterId")+n.html";
StringchapterFilePath=getServletContext(),getRealPath(7")+
chapterFileName;FilechapterFile=new
File(chapterFilePath);if(chapterFile.exists()){response.sendRedirect
(chapterFileName);return;}//如果有這個(gè)文件就告訴瀏覽器轉(zhuǎn)
向INovelChapterBiznovelChapterBiz=new
NovelChapterBizImplQ;Novelchapternovelchapter=
novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getP
arameter("chapterld")));//章節(jié)信息intlastPageld=
novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(),
novelChapter.getldO);intnextPageld=
novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId()/
novelChapter.getldO);request.setAttribute(nnovelchapter",
novelchapter);request.setAttribute("lastPageId",
lastPageld);request.setAttribute("nextPageId",
nextPageld);new
CreateStaticHTMLPage().createStaticHTMLPage(request,response,
getServletContext(),chapterFileName,chapterFilePath,
VbookRead.jsp");}}生成HTML靜態(tài)頁面的類:
packagecomjb.y2t034.thefifth.web.servlet;import
java.io.ByteArrayOutputStream;import
java.io.FileOutputStream;importjava.io.IOException;import
java.io.OutputStreamWriter;importjava.io.PrintWriter;import
javax.servlet.RequestDispatcher;import
javax.servlet.ServletContext;import
javax.servlet.ServletException;import
javax.servlet.ServletOutputStream;import
javax.servlet.http.HttpServletRequest;import
javax.scrvIct.http.HttpScrvletRcsponsc;import
javax.servlet.http.HttpServletResponseWrapper;/***創(chuàng)建HTML靜態(tài)頁
面*功能:創(chuàng)建HTML靜態(tài)頁面*時(shí)間:2009年1011日*地點(diǎn):home*
@authormavk**/publicclassCreateStaticHTMLPage{/***生
成靜態(tài)HTML頁面的方法*@paramrequest請(qǐng)求對(duì)象*@param
response響應(yīng)對(duì)象*@paramservletContextServlet上下文*
@paramfileName文件名稱*@paramfileFullPath文件完整路徑*
@paramjspPath需要生成靜態(tài)文件的JSP路徑(相對(duì)即可)*@throws
lOException*?throwsServletException*/publicvoid
createStaticHTMLPage(HttpServletRequestrequest,
HttpServletResponseresponse,ServletContextservletContext,String
fileName,StringfileFullPath,StringjspPath)throwsServletException,
IOException{response.setContentType("text/html;charset=gb231
2");〃設(shè)置HTML結(jié)果流編碼(即HTML文件編碼)RequestDispatcher
rd=servletContext.getRequestDispatcher(jspPath);//得至ljJSP資
源finalByteArrayOutputStreambyteArrayOutputStream=new
ByteArrayOutputStream();//用于從ServletOutputStream中接收資
源finalServletOutputStreamservletOuputStream=new
ServletOutputStream(){//用于從HttpServletResponse中接收資
源publicvoidwrite(byte[]b,intoffjnt
len){byteArrayOutputStream.write(b,off,
len);}publicvoidwrite(int
b){byteArrayOutputStream.write(b);));
inalPrintWriterprintwriternewPrintWriter(new
OutputStreamWriter(byteArrayOutputStream));〃把轉(zhuǎn)換字節(jié)流轉(zhuǎn)換成字符
流HttpServletResponsehttpServletResponse=new
HttpServletResponseWrapper(response){〃用于從response獲取結(jié)果流資
源(重寫了兩個(gè)方法)publicServletOutputStream
getOutputStream(){return
servletOuputStream;}publicPrintWriter
getWriter(){return
printWriter;}};rd.include(request,
httpServletResponse);〃發(fā)送結(jié)果流printWriter.flush();〃刷新緩沖
區(qū),把緩沖區(qū)的數(shù)據(jù)輸出FileOutputStreamfileOutputStream=new
FileOutputStream(fileFullPath);byteArrayOutputStream.writeTo(fil
eOutputStream);//把byteArrayOuputStream中的資源全部寫入到
fileOuputStream中fileOutputStream.close();〃關(guān)閉輸出流,并釋放
相關(guān)資源response.sendRedirect(fileName);〃發(fā)送指定文件流到客戶
端}}
三:高并發(fā)高負(fù)載類網(wǎng)站關(guān)注點(diǎn)之緩存、負(fù)載均衡、存儲(chǔ)
緩存是另一個(gè)大問題,我一般用memcached來做緩存集群,一般來說部署10
臺(tái)左右就差不多(10g內(nèi)存池)。需要注意一點(diǎn),千萬不能用使用swap,最好
關(guān)閉linux的sw叩。
負(fù)載均衡/加速可能上面說緩存的時(shí)候,有人第一想的是頁面靜態(tài)化,所謂的靜
態(tài)html,我認(rèn)為這是常識(shí),不屬于要點(diǎn)了。頁面的靜態(tài)化隨之帶來的是靜態(tài)服
務(wù)的負(fù)載均衡和加速。我認(rèn)為L(zhǎng)ighttped+Squid是最好的方式了。LVS
<>lighttped====>squid(s)====lighttpd
上面是我經(jīng)常用的。注意,我沒有用apache,除非特定的需求,否則我不部署
叩ache,因?yàn)槲乙话阌胮hp-fastcgi酉己合lighttpd,性能比apache+modjDhp
要強(qiáng)很多。
squid的使用可以解決文件的同步等等問題,但是需要注意,你要很好的監(jiān)控緩
存的命中率,盡可能的是高的90%以上。squid和lighttped也有很多的話題要
討論,這里不贅述。
存儲(chǔ)存儲(chǔ)也是一個(gè)大問題,一種是小文件的存儲(chǔ),比如圖片這類。另一種是大
文件的存儲(chǔ),比如搜索引擎的索引,一般單文件都超過2g以上。小文件的存儲(chǔ)
最簡(jiǎn)單的方法是結(jié)合lighttpd來進(jìn)行分布?;蛘吒纱嗍褂肦edhat的GFS,優(yōu)
點(diǎn)是應(yīng)用透明,缺點(diǎn)是費(fèi)用較高。我是指你購(gòu)買盤陣的問題。我的項(xiàng)目中,存儲(chǔ)
量是2?10Tb,我采用了分布式存儲(chǔ)。這里要解決文件的復(fù)制和冗余。這樣每個(gè)
文件有不同的冗余,這方面可以參考google的gfs的論文。大文件的存儲(chǔ),可
以參考nutch的方案,現(xiàn)在已經(jīng)獨(dú)立為hadoop子項(xiàng)目。(你可以googleit)
其他:此外,passport等也是考慮的,不過都屬于比較簡(jiǎn)單的了。四:高并發(fā)
高負(fù)載網(wǎng)站的系統(tǒng)架構(gòu)之圖片服務(wù)器分離大家知道,對(duì)于Web服務(wù)器來說,
不管是Apache.IIS還是其他容器,圖片是最消耗資源的,于是我們有必要將
圖片與頁面進(jìn)行分離,這是基本上大型網(wǎng)站都會(huì)采用的策略,他們都有獨(dú)立的
圖片服務(wù)器,甚至很多臺(tái)圖片服務(wù)器。這樣的架構(gòu)可以降低提供頁面訪問請(qǐng)求的
服務(wù)器系統(tǒng)壓力,并且可以保證系統(tǒng)不會(huì)因?yàn)閳D片問題而崩潰,在應(yīng)用服務(wù)器
和圖片服務(wù)器上,可以進(jìn)行不同的配置優(yōu)化,比如apache在配置ContentType
的時(shí)候可以盡量少支持,盡可能少的LoadModule,保證更高的系統(tǒng)消耗和執(zhí)
行效率。
利用Apache實(shí)現(xiàn)圖片服務(wù)器的分離緣由:起步階段的應(yīng)用,都可能部署在一
臺(tái)服務(wù)器上(費(fèi)用上的原因)第一個(gè)優(yōu)先分離的肯定是數(shù)據(jù)庫(kù)和應(yīng)用服務(wù)器。第
二個(gè)分離的,會(huì)是什么呢?各有各的考慮,我所在的項(xiàng)目組重點(diǎn)考慮的節(jié)約帶寬,
服務(wù)器性能再好,帶寬再高,并發(fā)來了,也容易撐不住。因此,我這篇文章的重
點(diǎn)在這里。這里重點(diǎn)是介紹實(shí)踐,不一定符合所有情況,供看者參考吧,環(huán)境
介紹:WEB應(yīng)用服務(wù)器:4CPU雙核2G,內(nèi)存4G部署:Win2003/Apache
HttpServer2.1/Tomcat6數(shù)據(jù)庫(kù)服務(wù)器:4CPU雙核2G,內(nèi)存4G部署:
Win2003/MSSQL2000步驟:步驟一:增力口2臺(tái)配置為:2CPU雙核2G,內(nèi)
存2G普通服務(wù)器,做資源服務(wù)器部署:Tomcat6,跑了一個(gè)圖片上傳的簡(jiǎn)單
應(yīng)用,(記得指定web.xml的〈distributable/〉),并指定域名為
采用協(xié)議步驟二:修改
resl.***.comzres2.***.com,ajpApachehttpd.conf
配置原來應(yīng)用的文件上傳功能網(wǎng)址為:1、/fileupload.html2、
/otherupload.html在httpd.conf中增加如下配置
<VirtualHost*:80>ServerAdminwebmaster@***.comProxyPass
7fileupload.htmlbalancer://rescluster/fileuploadIbmethod=byrequests
stickysession=JSESSIONIDnofailover=Offtimeout=5
maxattempts=3ProxyPass/otherupload.html
balancer://rescluster/otherupload.htmllbmethod=byrequests
stickysession=JSESSIONIDnofailover=Offtimeout=5
maxattempts=3#<!—負(fù)載均衡一,<Proxy
balancer://rescluster/>BalancerMemberajp://resl.***.com:8009
smax=5max=500ttl=120retry=300loadfactor=100
route=tomcatlBalancerMemberajp://res2.***.com:8009smax=5
max=500ttl=120retry=300loadfactor=100
route=tomcat2</Proxy></VirtualHost>步驟三,修改業(yè)務(wù)邏輯:所
有上傳文件在數(shù)據(jù)庫(kù)中均采用全url的方式保存,例如產(chǎn)品圖片路徑存成:
http://resl.***.com/upload/20090101/productl20302005.jpg
現(xiàn)在,你可以高枕無憂了,帶寬不夠時(shí),增加個(gè)幾十臺(tái)圖片服務(wù)器,只需要稍微
修改一下叩ache的配置文件,即可。
五:高并發(fā)高負(fù)載網(wǎng)站的系統(tǒng)架構(gòu)之?dāng)?shù)據(jù)庫(kù)集群和庫(kù)表散列
大型網(wǎng)站都有復(fù)雜的應(yīng)用,這些應(yīng)用必須使用數(shù)據(jù)庫(kù),那么在面對(duì)大量訪問的時(shí)
候,數(shù)據(jù)庫(kù)的瓶頸很快就能顯現(xiàn)出來,這時(shí)一臺(tái)數(shù)據(jù)庫(kù)將很快無法滿足應(yīng)用,于
是我們需要使用數(shù)據(jù)庫(kù)集群或者庫(kù)表散列。在數(shù)據(jù)庫(kù)集群方面
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 生物標(biāo)志物在藥物臨床試驗(yàn)中的精準(zhǔn)醫(yī)療策略-1
- 生物打印技術(shù)在牙周組織再生中的細(xì)胞因子調(diào)控
- 生物制劑失應(yīng)答后IBD的快速反應(yīng)評(píng)估方法
- 生物3D打印墨水的細(xì)胞凋亡抑制策略
- 生活質(zhì)量終點(diǎn)在慢性病藥物早期研發(fā)中的預(yù)測(cè)價(jià)值
- 人力資源崗面試題集及答案詳解
- 深度解析(2026)《GBT 19465-2004工業(yè)用異丁烷 (HC-600a)》
- 深度解析(2026)《GBT 19401-2003客運(yùn)拖牽索道技術(shù)規(guī)范》
- 瓣膜病合并感染性心內(nèi)膜炎治療策略
- 電商行業(yè)運(yùn)營(yíng)經(jīng)理面試技巧與題庫(kù)
- 變質(zhì)巖帶金屬礦勘查技術(shù)
- 學(xué)生實(shí)習(xí)家長(zhǎng)知情同意書(完美版)
- MOOC 光影律動(dòng)校園健身操舞-西南交通大學(xué) 中國(guó)大學(xué)慕課答案
- 英語雅思詞匯表
- 重型顱腦損傷患者的臨床觀察與護(hù)理
- CNG母站設(shè)備操作規(guī)程和作業(yè)指導(dǎo)書
- 如何長(zhǎng)高課件
- 23J916-1:住宅排氣道(一)
- 青島版科學(xué)四年級(jí)上冊(cè)知識(shí)點(diǎn)
- 宋小寶小品《碰瓷》完整臺(tái)詞
- 2023年06月北京第一實(shí)驗(yàn)學(xué)校招考聘用筆試題庫(kù)含答案解析
評(píng)論
0/150
提交評(píng)論