Java Thread: run() vs start()

17 November 2011

Java Thread: run() vs start()

剛在寫ANDROID,在使用到 audioRecord,所以用到了thread!
突然忘記要用run呢? 還是要用start?
查了一下資料,才找出差異性。


使用run呢,他是循序性的,也就是說他會跑完run裡面的程式,才會跳脫。
而start不是。
用個簡單的範例說明一下:
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("t1");
}
});

Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("t2");
}
}
});

上面我們宣告了2個thread,一個是t1,一個是t2。
都做完一千次才會停止。
他們分別會去印出自己是t1還是t2。
 如果我們是使用run,如下:
t1.run();
t2.run();

那麼印出來的值一定是像下面一樣
 t1 -> t1 -> t1 -> .........t1 ->  t2 -> t2 -> ......t2 
會先印完1000次的t1,才開始印1000次的t2。 但如果我們是使用start,如下:
t1.start();
t2.start();

結果就會相互交叉,
可能是t1->t1->t2->t1->t2..........
以此類推。










read more »


C++: Reference (參考)

16 November 2011

C++: Reference (參考)

前面一篇講了pointer,這篇要講只有C++才有的reference,
C是沒有reference的,相較於pointer,reference顯得平易近人多了!
reference有個很大的特性,它的意思是別名(alias)的意思!
reference不像pointer記錄著變數的記憶體位置,它只是變數的別名!

下面用個簡單的例子講解:

int iValue = 2;
int &iReference = iValue;
cout << iReference << endl; //會印出2
cout << &iReference << endl; //會印出iValue 的記憶體位置
cout << &iValue << endl;    //會印出iValue本身自己的記憶體位置

上面的範例宣告了一個整數變數(iValue),和一個參考變數(iReference) 第一行會先印出2,
因為前面說過參考只是別名, 意思就是說iReference是iValue的別名,
在白話一點iReference等於iValue,
所以第二行會印出iReference(也就是iValue)的記憶體位置,假設印出0x28ff44(每台電腦都不一定是這個值)
第三行就是印出iValue自己的記憶體位置,所以!!!它也會印出0x28ff44!! 跟第二行一樣!! (因為他們兩個相等咩)

reference跟pointer不一樣的還有幾點,
reference一定要有初始值!!!
取值不需要加上*!!

不過其實參考使用的時機大部分是用在函數時, 因為是別名,所以可以避免複製大量的變數到函數去(就算是pointer函數,也會複製)
下面是一個簡單的參考函數範例:

void fnReference(int &iValue){
iValue = iValue +1;
cout << iValue << endl;
}
main(){

int iValue = 2;
fnReference(iValue);
cout << iValue << endl;

system("pause");
return 0;
}


在上面的範例我們宣告了一個函數(fnReference),其傳遞參數為參考型態(&iValue)
在主程式中(main),傳遞了單純的整數變數進去,
跟pointer不一樣,pointer是傳記憶體位置進去,
參考就直接傳普通的變數進去,
我們在函數中把傳遞進去的參數+1,然後印出,會印出3,
回到主程式以後,在印出iValue,一樣會印出3。
因為我們是傳遞參考,這就是call by reference!

最後,reference還有一個跟pointer不一樣的點!
就是reference不能用來進行運算!!!!!






read more »


C++: pointer (指標)

16 November 2011

學C/C++,我想pointer(指標)是最大的門檻吧!
這也是大部分人學C/C++,最痛的東西吧!
這篇就稍微的講解pointer!

pointer是專門用來儲存某變數記憶體位置!
每宣告一個pointer時,就會配置一塊4 bytes的記憶體空間,
專門用來儲存某變數的記憶體位置。
下面用簡單的code來說明,
int iValue = 10;
int *iPointer = &iValue;

printf("iPointer的value=%d \r\n" , *iPointer); //取值要用*
printf("iPointer儲存value的address=%X \r\n" , iPointer); //沒有*就是印出本身儲存的記憶體位置
printf("iPointer本身的address=%X \r\n" , &iPointer); //取得記憶體位置都是用&
printf("iValue 本身的address=%X \r\n" , &iValue); //取得記憶體位置都是用&
printf("iPointer的size=%d \r\n" , sizeof(iPointer));
printf("iValue的size=%d \r\n" , sizeof(iValue));





下面為執行結果以及說明,:
output    說明
   iPointer的value=10印出儲存的記憶體位置本身的value,前面說過pointer是用來儲存記憶體位置,
如果要取得該記憶體位置的value,就是利用*
   iPointer儲存value的address=28FF3C印出iPointer儲存的資訊(記憶體位置)
   iPointer本身的address=28FF38iPointer自己的記憶體起始位置在哪
   iValue  本身的address=28FF3C第四行就是印出iValue本身的記憶體起始位置,會發現跟第二行一樣,因為iPointer就是儲存這個資訊
   iPointer的size=4印出iPointer的大小,前面說過,每個pointer的大小都為4 bytes,不論型態為和
   iValue的size=4印出iValue本身的大小,因為是interger,所以為4 bytes


上面為基本用法。
pointer也很常用來做字串的處理。
原因是用指標處理字串較省記憶體空間,也比較彈性,
我們可以宣告一個字串指標指向一個字串常數,
下面是個簡單的範例:
char *pValue[2]     = {"Ken","Yang"};
char szValue[2][10] = {"Ken","Yang"};
printf("szValue的value=%s \r\n" , szValue[0]);
printf("pValue的value=%s \r\n" , pValue[0]);
printf("szValue的size=%d \r\n" , sizeof(szValue));
printf("pValue的size=%d \r\n" , sizeof(pValue));



下面為執行結果以及說明,顏色相同的為該對應的結果及說明:
output    說明
  szValue的value=Ken印出儲存在陣列0的value
  pValue的value=Ken印出儲存在指標陣列0的value
  szValue的size=20字元陣列的大小為20
  pValue的size=8指標陣列的大小為8

可以發現陣列以及指標陣列的第0項,都是ken阿,可是大小卻都不一樣!
陣列的大小為20,而指標陣列為8
這就是為什麼使用指標會較為省空間的原因,且也較為彈性
因為字串指標是可以更改值的,可是字元陣列是不行的。

指標還有個特性,就是可以用來做運算,
可以看下面簡單的範例,
char *pString = "Ken";
cout << pString << endl;
cout << *(pString+1) << endl;
cout << sizeof(pString) << endl;
cout << sizeof(*(pString+1)) << endl;
cout << &pString << endl;


上面的例子,第一行我們先宣告字串指標,然後指定一個字串常數給他,
第二行就是印出value來(會印出Ken)
第三行就是進行指標的運算(會印出e,如果我們改成+2,就變成n)
第四行是印出大小,會印出4,因為說過指標的長度都固定為4
第五行也是印出大小,差別是印出該位置的字元大小,那就一定是1了
第六行就是印出該記憶體位置了,會發現字串指標跟前面講的變數指標(int, double..之類的)存取value或者存取記憶體的方式都不太同。


最後要講的是指標函數,用個簡單的範例來說明,
void fnPointer(int *pValue){
*pValue=*pValue+1;
cout << pValue << endl; //印出記憶體位置
}
main(){
int iValue = 2;
cout << &iValue << endl;
fnPointer(&iValue); //傳遞int變數的記憶體位置進去
cout << iValue << endl;
}

我們先宣告一個函數,那個函數裡的參數是pointer型態,
那麼使用方式就是傳遞某變數的記憶體位置進去即可,
因為我們說過指標是用來存某變數的記憶體位置!!!
所以就是傳遞記憶體位置進去。
然後我們再函數fnPointer裡面對value進行+1的動作,
然後在印出傳遞進來pointer的記憶體位置,
而主程式則是先印出iValue的記憶體位置,
在印出iValue的值。
會發現,主程式跟函數印出來的記憶體位置都相同!!
且在函數裡面進行+1以後,最後在main印出的value會變成3。
如果有些人可能會認為還是印出2,代表對pointer的概念還是不太了解(囧),因為是pointer,還是存取到原本的變數啊!
所以也是對原本的變數做操作!!!
印出2的方式我們稱為call by value,
但印出3的方式我們稱為call by address!
還有一種是call by reference!
後面一篇會講道!


以上是pointer一些簡單的介紹!
下一篇會介紹c++才有的參考(reference)























read more »