Evan's Blog

          Java, software development and others.

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            28 隨筆 :: 0 文章 :: 73 評論 :: 0 Trackbacks

          #

          J2SE 5.0在多線程上做了很大的改進,提供了更多的API,包括:
          Atomic variables: A set of classes that provide threadsafe operations without synchronization
          Explicit locks: Synchronization locks that can be acquired and released programmatically
          Condition variables: Variables that can be the subject of a targeted notification when certain conditions exist
          Queues: Collection classes that are thread-aware Synchronization primitives: New classes that perform complex types of synchronization
          Thread pools: Classes that can manage a pool of threads to run certain tasks
          Thread schedulers: Classes that can execute tasks at a particular point in time

          在《Java Threads》一書中將其歸納為三類:
          1. 對現有功能的新實現;
          2. 提供了重要的多線程工具,如線程池(pool)和計劃(schedule);
          3. 最小化同步工具(Minimal synchronization utilities)。

          這些功能的妙處我現在自然是無法體會得到,但對于JDK 5.0中提供的這些多線程工具,會不會也遭遇JDK 1.4提供的Log API的命運,因敵不過第三方工具而成為擺設呢(至少目前我還在用Log4J,且其也沒有停止開發的跡象)?
          posted @ 2006-03-05 23:25 Evan 閱讀(422) | 評論 (0)編輯 收藏

          Chapter2: Thread Creation and Management

          2.1 What Is a Thread?

          介紹了什么是線程,以及線程(thread, multithread)與進程(process, mutltitask)的區別。其中的一個重要區別是對共享數據的訪問。進程可以共享操作系統級別的某些數據區域,如剪貼板;而線程是對程序自有的數據進行共享。進程之間對共享數據的存取方法是特殊的,因此自然能夠得到程序員的注意;而線程之間對共享數據的存取與對線程自己的數據的存取方法是一樣的,所以常常比較隱蔽,而被程序員忽略。其實,這也是多線程開發比較難的地方。所以,這一節最后說:"A thread, then, is a discrete task that operates on data shared with other threads.(線程就是一個在與其它線程共享的數據上進行操作的單獨任務。)"

          2.2 Creating a Thread

          1. 有兩種方法創建線程:使用Thread類或者Runnable接口
          2. 示例程序竟然是編一個打字游戲,所以,這本書的門檻還是有點高的:(。當然可以從該書的站點直接下載代碼

          3. Thread class
          package java.lang;
          public class Thread implements Runnable {
          public Thread( );
          public Thread(Runnable target);
          public Thread(ThreadGroup group, Runnable target);
          public Thread(String name);
          public Thread(ThreadGroup group, String name);
          public Thread(Runnable target, String name);
          public Thread(ThreadGroup group, Runnable target, String name);
          public Thread(ThreadGroup group, Runnable target, String name,
          long stackSize);
          public void start( );
          public void run( );
          }
          Thread name: 線程名,用以打印線程信息時用,缺省為Thread-N。
          Runnable target:可運行的目標。一個可運行的對象就是一串可由線程執行的指令。缺省就是在run()方法中編寫的內容。
          Thread group:線程組。對于大多數應用來說沒什么意義,缺省在同一組。
          Stack size:線程堆棧大小,與平臺相關。為了使程序更具可移植性,并不推薦使用。

          2.3 The Lifecycle of a Thread

           

          1. Creating a Thread:創建一個線程對象,并沒有開始執行一個線程
          2. Starting a Thread:在調用線程對象的start()方法前,一直處于等待狀態。可以通過調用isAlive()方法來獲取線程是否正在運行;
          3. Terminating a Thread:線程在以下情況下結束  
            1)執行完run()中的語句;
            2)拋出一個異常,包括其沒有捕獲的異常;
            3)其所在的程序(或者容器)調用System.exit()。
          注意:一個線程結束后,就不能再次啟動,該線程就變成一個普通的對象,如果試圖再次調用start()方法,將拋出java.lang.IllegalThreadStateException異常。如果想多次運行,要么創建新的對象;要么就是不要結束該線程。
          4. Java并沒有提供可靠的方法來暫停、掛起或者重啟一個線程的方法,線程本身能通過sleep()函數來暫停執行。目前依然只能確保若干毫秒級別的精度。
          5. Thread Cleanup:線程終止后,線程對象依然存在。可以通過join()方法以阻塞方式(blocked)來等待某個線程終止。

          2.4 Two Approches to Stop a Thread

          1. Setting a Flag:在線程的執行過程中判斷其它線程是否將標志置位。其缺點是有時間延遲,尤其是當進入了某些被阻塞的函數如:sleep(), wait()等;
          2. 調用線程的interrupt()方法,線程的執行過程中改為判斷isInterrupted()的返回值。可以解決線程進入阻塞導致的延遲,但依然解決不了超長時間計算而導致的延遲。interrupt()有兩個作用:1)終止sleep()和wait(),拋出InterruptedException;2)使isInterrupted()返回true。下面這段代碼將演示interrupt()的作用:

          public class TestInterrupted {
          public static void main(String args[]) throws InterruptedException{
          Foo foo = new Foo();
          foo.start();
          Thread.currentThread().sleep(100); //注釋掉這句有什么影響呢?
          System.out.println("before interrupt");
          foo.interrupt();
          System.out.println("after interrupt");
          } }

          class Foo extends Thread {
          public void run() {
          try{
          while(!isInterrupted()) {
          System.out.println("start calculating...");
          double pi = 3.1415926;
          for(int i=0; i<5; i++) {
          for(long j=0; j<1000000; j++) {
          pi *= pi;
          }
          System.out.println("i="+i);
          }
          System.out.println("before sleep");
          sleep(5000); //注釋掉這句及相關的try...catch語句,又怎樣呢?
          System.out.println("after sleep");
          }
          } catch(InterruptedException ex) {
          ex.printStackTrace(System.out);
          }
          }
          }

           

          2.5 The Runnable Interface

          為什么有了Thread類,還要有Runnable接口呢?最主要的原因是為了解決Java不能多重繼承的問題。線程繼承自Thread,還是僅僅實現Runnable接口,取決于這個線程的作用。不過,如果僅僅實現Runnable接口,則在線程里不能使用Thread類的方法,比如interrupt()和isInterrupted()。當然,這個還是要取決于實際情況。

          2.6 Threads and Objects

          主要講解線程與對象的關系。線程根本上還是個對象,其可以存取任何對象包括其它線程對象,當然也能被其它對象存取,只要沒有因為爭奪公共資源而被鎖定,線程對象中的任何屬性和方法都有可能同時執行。并且Java中的鎖只針對對象本身,并不包括對象下的屬性;而對方法同步,則等同于對對象同步。更進一步的說明還可以參考《Practical Java》中的"實踐46:面對instance函數,synchronized鎖定的是對象(object)而非函數(methods)或代碼(code)"。下面用兩段代碼來說明一下:
          代碼1:

          public class TestLock {
          public static void main(String args[])
          throws InterruptedException{
          Foo foo = new Foo();
          foo.start();
          Thread t = Thread.currentThread();
          for(int i=0; i<10; i++) {
          foo.setInt2("Main", i, i+20);
          }
          }
          }

          class Foo extends Thread{
          protected int arrI[] = new int[10];

          public void run() {
          try {
          for(int i=0; i<10; i++) {
          setInt("Foo", i, i);
          }
          } catch(InterruptedException ex) {}
          }

          public synchronized void setInt(String from, int pos, int val)
          throws InterruptedException{
          arrI[pos] = val;
          sleep((long)(Math.random()*5000));
          System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
          }

          public void setInt2(String from, int pos, int val)
          throws InterruptedException {
          synchronized(arrI){
          arrI[pos] = val;
          sleep((long)(Math.random()*5000));
          System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
          }
          }
          }
          結果:非線程安全,setInt()在對象上加鎖,而setInt2()在屬性arrI上加鎖,不同的鎖不能保證線程安全。可能的結果如下:
          Foo:arrI[0]=0 
          Main:arrI[0]=0
          Main:arrI[1]=21
          Main:arrI[2]=22
          Foo:arrI[1]=21
          Main:arrI[3]=23
          Main:arrI[4]=24
          Main:arrI[5]=25
          Foo:arrI[2]=2
          Main:arrI[6]=26
          Main:arrI[7]=27
          Foo:arrI[3]=3
          Foo:arrI[4]=4
          Main:arrI[8]=28
          Main:arrI[9]=29
          Foo:arrI[5]=5
          Foo:arrI[6]=6
          Foo:arrI[7]=7
          Foo:arrI[8]=8
          Foo:arrI[9]=9

          代碼2:
          public class TestLock1 {
          public static void main(String args[])
          throws InterruptedException{
          Foo1 foo = new Foo1();
          foo.start();
          Thread t = Thread.currentThread();
          for(int i=0; i<10; i++) {
          foo.setInt2("Main", i, i+20);
          }
          }
          }

          class Foo1 extends Thread{
          protected int arrI[] = new int[10];

          public void run() {
          try{
          for(int i=0; i<10; i++) {
          setInt("Foo", i, i);
          }
          }catch(InterruptedException ex){}
          }

          public synchronized void setInt(String from, int pos, int val)
          throws InterruptedException{
          arrI[pos] = val;
          sleep((long)(Math.random()*5000));
          System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
          }

          public synchronized void setInt2(String from, int pos, int val)
          throws InterruptedException{
          arrI[pos] = val;
          sleep((long)(Math.random()*5000));
          System.out.println(from+":arrI["+pos+"]="+arrI[pos]);
            }
          }
          結果:線程安全
          posted @ 2006-03-05 23:25 Evan 閱讀(693) | 評論 (0)編輯 收藏

          Chapter 3. Data synchronization

          第二章中介紹了如何創建線程對象、啟動和終止線程。但多線程編程的關鍵在于多個線程之間數據的共享和同步,從這一章開始,將詳細介紹線程之間數據的共享和同步的各種方法。

          3.1 The Synchronized Keywor
          1. synchronized是Java中最基本也最常用的用來編寫多線程安全代碼的關鍵字,用以保護對多線程共享的數據的操作總是完整的;
          2. Atomic: 當一個操作被定義成原子操作時,意味著該操作在執行過程中不會被打斷;原子操作可以由硬件保證或者通過軟件來模擬;
          3. Mutex Lock: 在很多多線程系統,通過互斥鎖來保護的共享數據。Java中的任何一個對象都有一個與之相關的鎖,當一個方法被聲明成synchronized時,就表示當線程進入該方法前,必須獲得相應對象的鎖,在執行完畢再釋放這個鎖。從而保證同一時刻只有一個線程調用該對象上的被聲明為synchronized的方法。注意:Java的互斥鎖只能加在對象級上,獲得某個對象的鎖,并不能保證該對象的屬性和其它非synchronized的方法是線程安全的;也不能保證受保護的方法里調用的其它對象是多線程安全的,除非任何調用這些沒有被保護的方法或者對象只通過受保護的方法進行調用。所以,編寫線程安全的代碼關鍵就在于規劃方法和對象之間的調用關系,并盡量采用相同對象的鎖來進行同步控制。

          3.2 The Volatile Keyword
          1. Scope of a Lock: 鎖的作用范圍即獲得和釋放鎖之間的那段時間。
          2. Java標準雖然聲明存取一個非long和double變量的操作是原子操作,但由于不同虛擬機實現的差異,在多線程環境下每個線程可能會保留自己的工作拷貝,而導致變量的值產生沖突。為了避免這種情況的發生,可以有兩種方法:
            1) 為變量創建聲明為synchronized的setter和getter方法,然后任何調用(包括在類類部)該變量的地方都通過setter和getter方法;
            2) 采用volatile聲明,確保每次存取這些屬性時都從主內存中讀入或者寫入主內存中;
            3) volatile僅僅用于解決Java內存模式導致的問題,只能運用在對該變量只做一個單一裝載或寫入操作且該方法的其它操作并不依賴該變量的變化。如:在一個循環體中作為遞增或遞減變量時就不能使用volatile來解決線程同步的問題。
          3. volatile的使用是有限的,一般而言,僅僅將其作為強制虛擬機總是從主內存讀寫變量的一個手段,或者某些需要其參數聲明為volatile的函數。

          3.3 More on Race Conditions
          本節以打字游戲中顯示成績的例子來解釋了可能存在的race condition。關鍵要注意以下幾點:
          1. 操作系統會隨機的切換多個線程的運行,因此當多個線程調用同一個方法時,可能在任何地方被暫停而將控制權交給另外的線程;
          2. 為了減少被誤用的可能,總是假設方法有可能被多個線程調用;
          3. 鎖僅僅與某個特定實例相關,而與任何方法和類都無關,這一點當需要存取類屬性或方法時要特別注意;
          4. 任何時候只有一個線程能夠運行某個類中一個被聲明為synchronized的靜態方法;一個線程只能運行某個特定實例中一個被聲明為synchronized的非靜態方法。

          3.4 Explicit Locking
          1. 學過Win32下編寫多線程的朋友剛開始可能會被Java的Synchronized關鍵詞搞糊涂。因為Java中的任何一個對象都有一個與之相關的鎖,而不象在Win32下要先定義一個互斥量,然后再調用一個函數進入或者離開互斥區域。在JDK 1.5以后也開始提供這種顯示聲明的鎖。JDK 1.5中定義了一個Lock接口和一些類,允許程序員顯示的使用鎖對象。
          2. 在Lock接口里有兩個方法:lock()和unlock()用來獲取和釋放鎖對象,從而保證受保護的代碼區域是線程安全的。
          3. 使用鎖對象的一個好處在于可以被保存、傳遞和拋棄,以在比較復雜的多線程應用中使用統一的鎖。
          在使用鎖對象時,總是將lock()和unlock()調用包含在try/finally塊中,以防止運行時異常的拋出而導致死鎖的情況。

          3.5 Lock Scope
          利用lock()和unlock()方法,我們可以在任何地方使用它們,從一行代碼到跨越多個方法和對象,這樣就能根據程序設計需要來定義鎖的作用(scope of lock)范圍,而不是象以前局限在對象的層次上。

          3.5.1 Synchronized Blocks

          1. 利用synchronized關鍵字也能建立同步塊,而不一定非得同步整個方法。
          2. 同步一段代碼時,需要明確的指定獲取哪個對象的鎖(這就類似于鎖對象了),這樣,就可以在多個方法或對象中共享這個鎖對象。

          3.6 Choosing a Locking Mechanism
          使用鎖對象還是同步關鍵字(synchronized),這個取決于開發員自己。使用synchronized比較簡單,但相對而言,比較隱晦,在比較復雜的情況下(如要同時同步靜態和非靜態方法時),沒有鎖對象來得直觀和統一。一般而言,synchronized簡單,易于使用;但同時相對而言效率較低,且不能跨越多個方法。

          3.6.1 The Lock Interface
          public interface Lock {
          void lock();
          void lockInterruptibly() throws InterruptedException;
          boolean tryLock();
          boolean tryLock(long time, TimeUnit unit)
          throws InterruptedException;
          void unlock();
          Condition newCondition();
          }
          其中的tryLock()和tryLock(long, TimeUnit)將嘗試獲取鎖對象,如果不能獲取或在指定時間內不能獲取,將立即返回。調用者可以根據返回值來判斷是否獲得了鎖對象以做進一步的操作。

          3.7 Nested Locks
          1. 在一個同步方法內調用同一個對象上的另外的同步方法的情況,稱之為嵌套鎖(nested locking)。系統將自動執行嵌套的同步方法,而無須等待鎖的釋放。因此,有的時候,即使一些私有方法僅僅被已同步的方法調用,我們也給其加上synchronized關鍵字,以減少后續維護時可能產生的誤導。
          2. ReenterantLock類也支持嵌套鎖。在ReenterantLock類維持一個計數器,只有當這個計數器為0時,才會釋放鎖。注意:這個特性是ReenterantLock類的特性,而不是所有實現Lock接口的類的特性。
          3. 需要支持嵌套鎖的一個原因是方法之間交叉調用(cross-calling)。設想對象a的方法M1調用對象b的方法N1,然后N1再調用對象a的方法M2,而M1和M2都是同步方法,如果不支持嵌套鎖,則N1將在調用M2時等待M1釋放鎖,而M1則由于N1沒有返回永遠也不會釋放鎖,這樣就產生了死鎖。
          4. synchronized和Lock接口并沒有提供鎖對象被嵌套獲取的次數,但ReentrantLock則提供了這樣一種機制:
          public class ReentrantLock implements Lock {
          public int getHoldCount();
          public boolean isLocked();
          public boolean isHeldByCurrentThread();
          public int getQueueLength();
          ...
          }
          其中:
              1) getHoldCount()返回當前線程的獲取次數,返回0并不表示該鎖是可獲取的,有可能沒有被當前線程獲得;
              2) isLocked()判斷該鎖對象是否被任何線程獲得;
              3) isHeldByCurrentThread()判斷是否由當前線程獲得;
              4) getQueueLength()用來估計當前有多少線程在等待獲取這個鎖對象。

          3.8 Deadlock
          介紹了死鎖的概念,并修改例子代碼來演示deadlock的產生。死鎖一般產生在多個線程在多個鎖上同步時產生的;當然,多個線程在判斷多個條件的時候,也有可能產生死鎖。

          3.9 Lock Fairness
          1. Java里鎖的獲取機制依賴于底層多線程系統的實現,并不保證一個特定的順序;
          2. ReentrantLock類提供一個先進先出(first-in-first-out)的獲取鎖的選項(在創建鎖對象時傳入true值)。
          文章來源:http://blog.csdn.net/evanwhj/archive/2006/03/05/616068.aspx
          posted @ 2006-03-05 23:25 Evan 閱讀(505) | 評論 (0)編輯 收藏

          從2006年第五期的《讀者》上看到下面幾段言論,覺得頗有點意思,摘錄如下:
          互聯網就像是酒,看你怎么用,如果你生性孤僻,互聯網會讓你更加孤僻,如果你要和別人交流,它也會很容易讓你和別人交流。
          ——某位技術專家說
          其實,按我的說法,互聯網應該是個加速器,它往往會加劇你性格中不太容易控制的方面而變得益發不可收拾。當然,這只是對于12px的普通網友而言;而少數精英卻能從中獲得不菲的名利。

          愛情之酒甜而苦。兩人喝,是甘露;三人喝,是酸醋;隨便喝,要中毒。
          ——陶行知

          不是懷鄉,沒有鄉愁;不是近鄉,沒有情怯;不是還鄉,沒有衣錦;不是林黛玉,沒有眼淚。
          ——李敖自述訪問大陸的心情
          不管怎樣說,李大師還是很有才氣的,并且他特立獨行、有仇必報的性格——不管好壞——也是頗令人欽佩的。只是畢竟歲月不饒人,李大師越來越有點叨嘮的問題了。同樣的一些話、一些事會在一系列相關的場合連續不斷的說,不怕你耳朵不起繭。就像如果人家問他的風流趣事,他基本上都會說那個17朵玫瑰的故事一樣。然后一眾主持和現場觀眾都一定會做出欽佩至極,大呼高明狀。

          情如魚水是夫妻雙方最高的追求,但是我們都容易犯一個錯誤,即總認為自己是水,而對方是魚。
          ——BBS經典語錄
          其實,總有一個是魚,一個是水的。再說,也不一定是水的必定占上風呀。無水的魚固然活不了,但聰明的魚總會在干死前跳到另外的水中;而無魚的水,也必會少了生機,甚而至于發臭了。

          人要有三個頭腦:天生的一個頭腦,從書中得來的一個頭腦,從生活中得來的一個頭腦。
          ——契珂夫
          人往往比較容易受第一個頭腦的控制,受第三個頭腦的誘惑,第二個頭腦往往比較難以獲得,在決策時也比較難以取得主動權。

          除非你是比爾.蓋茨,否則你跟破產之間僅有一場重病之隔。
          ——美國進行的一項調查發現,美國有半數破產者是被猛漲的醫藥費所拖累,主持這項調查的一位教授如此感嘆。
          如果這不是托,那么中國的現狀似乎也不是個別的現象。但是,在中國,也許還有另外一個結局,那就是等死,即使得的不是絕癥

          posted @ 2006-03-05 23:25 Evan 閱讀(278) | 評論 (0)編輯 收藏


          播放視頻文件

          引用內容
          我在這兒等著你回來
          等著你回來
          看那桃花開
          把那花兒采
          桃花朵朵開
          暖暖的春風迎面吹
          枝頭鳥兒成雙對
          情人心花兒開
          啊喲啊喲
          你比花還美妙
          叫我忘不了
          秋又去春又來
          記得我的愛
          給你把花戴
          嘗嘗家鄉菜
          團圓樂開懷
          暖暖的春風迎面收
          別把我忘懷
          把那花兒揀
          【聽后感】對我而言,阿牛的歌,屬于還能聽一聽的范圍,至少可以讓人輕松一點,開心一下。阿牛春節前去臺灣宣傳,上吳宗憲的節目,被吳惡搞了一把,喝掉大半扎各種調料混在一起的東東,主持和其他嘉賓在前面自娛自樂去了,他一個人在旁邊默默地喝著。然后吳回過來頭大吃一驚,說:“誰讓你全喝掉的。”為表風范,吳表示要陪喝,可是連一口也喝不下去的。可見阿牛有多么老實天真了。估計,阿牛以后看到吳宗憲的背影就怕了,呵呵。



          文章來源:http://blog.csdn.net/evanwhj/archive/2006/03/05/616108.aspx
          posted @ 2006-03-05 23:25 Evan 閱讀(336) | 評論 (0)編輯 收藏

          播放視頻文件
          ?

          故事背景是很感人的網絡小說《你的肩上有蜻蜓么》
          引用內容
          有一對非常恩愛的戀人,他們每天都去海邊看日出,晚上去海邊送夕陽,可是有一天,在一場車禍中,女孩不幸受了重傷,幾天幾夜都沒有醒過來,男孩日夜守在床前,哭干了眼淚。

          一個月過去了,女孩仍然昏睡,而男孩早已憔悴不堪了,看他仍苦苦支撐。上帝被他感動了,決定給這個執著的男孩一個例外,上帝問他:“你愿意用你自己的生命作為交換嗎?”男孩毫不猶豫的回答“我愿意”上帝說:“那好吧,我可以讓你的戀人很快醒來,看你要答應我 化做三年的蜻蜓。”

          天亮了,南海變成了一只蜻蜓,他匆匆地飛到了醫院,女孩真的醒了,她還在跟身旁的一名醫生在交談。

          女孩出院了,但是她并不快樂。她四處打聽男孩的下落,女孩整天不停地尋找,早已化成蜻蜓的男孩卻無時無刻不圍繞在的身邊,只是他不會呼喊,不會擁抱,他只能默默地承受著她視而不見。夏天過去了,蜻蜓不得不離開這里,他最后一次飛落在女孩的肩上。他想用細小的嘴來親親她的額頭,然而他弱小的身體不足以被她發現。春天來了,蜻蜓迫不及待地飛回來,然而,她那熟悉的身影旁站著高大而英俊的男人,那一剎那,蜻蜓幾乎快從半空中跌落下來。蜻蜓傷心極了,他常常會看到那個男人帶著自己的戀人在海邊看日出,晚上又在海邊看日落,而他自己除了偶然能停落在的肩上之外,什么也做不了。第三年夏天,蜻蜓已不再常常去看望自己的戀人了。她的肩被男醫生擁著,臉被男醫生輕輕地吻著,根本沒時間去留意一只傷心的蜻蜓,更沒有心情去懷念過去。三年的期限很快就要到了。最后一天,蜻蜓昔日的戀人跟那個男醫生舉行了婚禮。

          蜻蜓悄悄地飛進了教堂,落在上帝的肩膀上,他聽到下面的戀人對上帝發誓說“我愿意”他看著男醫生把戒指戴到昔日戀人的手上,然后他看見他們甜蜜地親吻。蜻蜓流下了傷心的眼淚。

          上帝嘆息著:“你后悔了嗎?”蜻蜓擦干了眼淚:“沒有!”上帝又帶著一絲愉悅說:“明天你就可以變回你自己了。”蜻蜓搖搖頭說:“就讓我一輩子做蜻蜓吧……”

          有些緣分是注定要失去的,愛一個人不一定要擁有,但是擁有一個人就一定要好好去愛他。你的肩上有蜻蜓嗎?
          【聽后感】歌曲還沒有細聽,但覺得沒有那篇小說來得感人,就像電影怎么拍也拍不出原著的味道;小說比較感人,但換了我,寧愿堅持等她醒來;或者讓上帝給我另外一個選擇,那就是雙雙化成蝴蝶,所以梁山伯與祝英臺的故事比較符合中國人的口味。另外就是,愛人之間的愛一定要是雙向的;如果三年后發現女孩不愛我了,用不著后悔,但我必然會再變成人,去找我的真愛。
          posted @ 2006-03-05 23:25 Evan 閱讀(1838) | 評論 (6)編輯 收藏


          昨天晚上上了床,拿著遙控器隨便轉著臺,突然看到周星馳的《喜劇之王》,又碰巧看到飄飄(張柏芝飾)去看伊天仇(周星馳飾)自導自演精武門,然后飄飄也自說自話地上臺湊熱鬧,被伊天仇摔了個四腳朝天,然后坐在海灘邊聊天。這時,他們之間有這樣一段對話:
            飄飄:前面漆黑一片,什么也看不到。
            伊天仇:可是等到天亮,景色就會很美麗了。
          這個對話大概就是這樣子,是啊,如果你現在眼前一片漆黑,那倒真用不著怎樣害怕,天也許就快亮了。怕的就是,眼前白茫茫一片,分不清到底是快天亮了呢,還是天要黑了。

          接下來,飄飄就和伊天仇一夜風流,處于人生最低谷的伊天仇不知道這是愛情呢,還是僅僅一夜情,于是翻箱倒柜,將能找到的所有錢、手表之類的全部放在了飄飄的衣服上,繼續裝睡。而飄飄呢,也以為伊天仇僅僅是將自己當作風塵女子,也只能瀟灑地走開。然而,當伊天仇追出來說:“我養你”的時候,我覺得應該是全劇最精彩的情節之一了。兩個處于社會底層且又在自己最失意的時候,終于能夠找到相互欣賞和珍惜的愛人,的確是比較感人的。難怪飄飄在出租車里拿出伊天仇一直看的那本怎樣當喜劇演員的書時會淚流滿面了。

          唉,現在看片子,有的時候連這樣一句兩句令人欣賞的臺詞也沒有了。

          文章來源:http://blog.csdn.net/evanwhj/archive/2006/03/05/616120.aspx
          posted @ 2006-03-05 23:25 Evan 閱讀(375) | 評論 (0)編輯 收藏

          僅列出標題
          共3頁: 上一頁 1 2 3 
          主站蜘蛛池模板: 宿迁市| 诸暨市| 珠海市| 龙南县| 广宁县| 舟曲县| 漳州市| 宝兴县| 康乐县| 大厂| 贺兰县| 毕节市| 达州市| 张家口市| 高平市| 瓦房店市| 威信县| 唐河县| 镇赉县| 江孜县| 洪江市| 朝阳区| 桓台县| 扎兰屯市| 渭南市| 军事| 双江| 哈尔滨市| 克拉玛依市| 玉环县| 雅江县| 东乡族自治县| 韶山市| 岗巴县| 宁强县| 西昌市| 博爱县| 东明县| 彰武县| 融水| 西充县|