posts - 51, comments - 17, trackbacks - 0, articles - 9
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          java 線程

          Posted on 2007-04-08 17:14 chenweicai 閱讀(188) 評論(0)  編輯  收藏

          java實現(xiàn)多線程有兩種方法:
          一種是繼承Thread類

          如下面例子:
          public class TestThread extends Thread {

           //實現(xiàn)多線程方法一:繼承Thread類,并重載run方法
           public void run(){
            //要將一段代碼在一個新的線程上運行,該代碼應(yīng)寫在run函數(shù)中
            while(true){
             System.out.println(Thread.currentThread().getName() + "is running...");
            }
           }
          }



          public class ThreadDemo2 {

           public static void main(String[] args) {
            
            //啟動一個新的線程,不是直接調(diào)用Thread類子類對象的run方法,
            //而是調(diào)用Thread類子類對象的start方法,Thread類對象的start方法
            //將產(chǎn)生新的線程,并在該線程上運行該Thread類對象中的run方法,根據(jù)
            //多態(tài)性 實際上運行的是Thread子類的run方法
            TestThread testThread = new TestThread();
            testThread.start();
            
            while(true){
             System.out.println("main thread is running...");
            }
           }

          }



          方法二是:實現(xiàn)接口Runnable中的run函數(shù)

          如下列所示

          //實現(xiàn)多線程方法二:實現(xiàn)Runnable接口,重載run函數(shù),
          //大多數(shù)情況下,如果只想重寫 run() 方法,而不重寫其他 Thread 方法,
          //那么應(yīng)使用 Runnable 接口。這很重要,
          //因為除非程序員打算修改或增強類的基本行為,否則不應(yīng)為該類創(chuàng)建子類。
          public class TestThread implements Runnable {

           public void run() {
            // TODO Auto-generated method stub
            System.out.println(Thread.currentThread().getName() + "is running......");
           }
           
          }


           public static void main(String[] args) {
            // TODO Auto-generated method stub
            TestThread testThread = new TestThread();//創(chuàng)建TestThread類的一個實例
            Thread thread = new Thread(testThread);//創(chuàng)建一個Thread類的實例
            thread.start();//使線程進入runnable狀態(tài)
            
            while(true){
             System.out.println("main thread is running...");
            }
           }


          2.這兩種方法的區(qū)別:實現(xiàn)Runnable接口適合多個相同的程序代碼訪問處理同一資源


          如下列所示:
          //四個售票窗口售同一中車票,總共有100張,要求這四個售票多線程進行
          public class TicketRunnable implements Runnable {

           private int tickets = 100;
           public void run() {
             while(true){
              if(tickets > 0){
               System.out.println(Thread.currentThread().getName() +
                 " is saling ticket " + tickets--);
              }
             }
           }

          }

          public class TicketRunnableDemo {

           public static void main(String[] args){
            //創(chuàng)建了四個線程,每個線程調(diào)用了同一各TicketRunnable對象中run方法,
            //訪問的是同一個對象中的變量tickets,從而滿足了我們的要求。
            //實現(xiàn)Runnable接口適合多個相同的程序代碼訪問處理同一資源
            TicketRunnable ticketrunnable = new TicketRunnable();
            new Thread(ticketrunnable).start();
            new Thread(ticketrunnable).start();
            new Thread(ticketrunnable).start();
            new Thread(ticketrunnable).start();
           }
          }

          而繼承繼承Thread類,并重載run方法不能達到此目的
          如下所示:
          public class TicketThread extends Thread {

           private int tickets = 100;
           
           public void run(){
            while(true){
             if(tickets>0){
              System.out.println(Thread.currentThread().getName() +
                "is saling ticket " + tickets--);
             }
            }
           }
          }

          public class TicketThreadDemo {

           public static void main(String[] args){
            //我們希望的是四個線程共售100,我們創(chuàng)建四個線程
            //但結(jié)果與我們希望的相反,各個線程各售100張票
            new TicketThread().start();
            new TicketThread().start();
            new TicketThread().start();
            new TicketThread().start();
            
          //  如果我們象下面這樣寫的話,只有一個線程在售票,沒有實現(xiàn)四個線程并發(fā)售票
          //  TicketThread ticketThread = new TicketThread();
          //  ticketThread.start();
          //  ticketThread.start();
          //  ticketThread.start();
          //  ticketThread.start();
           }
          }

          3.后臺線程

          public class DaemonTest {
           public static void main(String[] args){
            TicketRunnable ticketRunnable = new TicketRunnable();
            Thread thread = new Thread(ticketRunnable);
            thread.setDaemon(true);//將此線程設(shè)置為后臺線程,當進程中只有后臺線程時,進程就會結(jié)束
            thread.start();
           }
          }

          4.聯(lián)合線程
          (還沒搞懂)

          5. 線程同步

          在上面的售票程序中,線程可能是不安全的,

          比如我們修改一下:

          public class ThreadRunnable implements Runnable{
           
           private int tickets = 100;
           public void run() {
             while(true){
              if(tickets > 0){
               try{
                Thread.sleep(10);//使該線程暫停,
               }catch(Exception e){
                System.out.println(e.getMessage());
               }
               System.out.println(Thread.currentThread().getName() +
                 " is saling ticket " + tickets--);
              }
             }
           }
          }

          再次測試時,發(fā)現(xiàn)可能會打印-1 -2 這樣的ticket

          所以我們要修改一下,使該程序是線程安全的,

          public class TicketSynch implements Runnable{
           
           private int tickets = 100;
           String str = new String("");//此對象放在run函數(shù)之外
           
           public void run(){
            while(true){
             synchronized(str){//同步代碼塊
              if(tickets > 0){
               try{
                Thread.sleep(10);
               }
               catch(Exception e){
                System.out.println(e.getMessage());
               }
               System.out.println(Thread.currentThread().getName()
                 +" is saling ticket " + tickets--);
              }
             }
            }
           }

          }

          但是 同步以犧牲程序的性能為代價

          5. 同步函數(shù)

          public class SynchMethod implements Runnable{

           private int tickets = 100;
           public void run(){
            while(true){
             sale();
            }
           }
           
           public synchronized void sale(){
            if(tickets > 0){
             try{
              Thread.sleep(10);
             }catch(Exception e){
              System.out.println(e.getMessage());
             }
             System.out.println(Thread.currentThread().getName()
               + "is saling ticket " + tickets--);
            }
           }
          }

           public static void main(String[] args){
            //創(chuàng)建了四個線程,每個線程調(diào)用了同一各TicketRunnable對象中run方法,
            //訪問的是同一個對象中的變量tickets,從而滿足了我們的要求。
            //實現(xiàn)Runnable接口適合多個相同的程序代碼訪問處理同一資源
            SynchMethod synchMethod = new SynchMethod();
            new Thread(synchMethod).start();
            new Thread(synchMethod).start();
            new Thread(synchMethod).start();
            new Thread(synchMethod).start();
           }

          6.代碼塊和函數(shù)間的同步
          public class MethodAndBlockSyn implements Runnable{

           private int tickets = 100;
           String str = new String("");
           
           public void run(){
            if(str.equals("method")){
             while(true){
              sale();
             }
            }
            else{
             synchronized(str){//同步代碼塊
              if(tickets > 0){
               try{
                Thread.sleep(10);
               }
               catch(Exception e){
                System.out.println(e.getMessage());
               }
               System.out.println(Thread.currentThread().getName()
                 +" is saling ticket " + tickets--);
              }
             }
            }
           }
           
           
           public synchronized void sale(){
            if(tickets > 0){
             try{
              Thread.sleep(10);
             }catch(Exception e){
              System.out.println(e.getMessage());
             }
             System.out.println(Thread.currentThread().getName()
               + "is saling ticket " + tickets--);
            }
           }
          }


           public static void main(String[] args){
            MethodAndBlockSyn test = new MethodAndBlockSyn();
            new Thread(test).start();// 這個線程調(diào)用同步代碼塊
            
            try{
             Thread.sleep(1);//讓線程等待100ms 是為了讓該線程得到CPU
             //避免該線程未得到CPU就將str設(shè)置為method,從而使此線程也是調(diào)用同步函數(shù)
            }catch(Exception e)
            {
            }
            test.str = new String("method");
            new Thread(test).start();//這個線程調(diào)用同步函數(shù)
           }

           

          7. 線程間通訊

          wait: 告訴當前線程放棄監(jiān)視器并進入睡眠狀態(tài),知道有其他線程進入同一監(jiān)視器并調(diào)用notify為止。

          notify:喚醒同一對象監(jiān)視器中調(diào)用wait的第一個線程。類似飯館有一個空位置后通知所有等待就餐顧客中的第一位可以入座的情況

          notifyAll:喚醒同一對象監(jiān)視器中調(diào)用wait的所有線程,具有最高優(yōu)先級的程序先被喚醒并執(zhí)行。

          以上三個方法只能在synchronized方法中調(diào)用

          public class Record {

           private String name = "陳世美";
           private String sex = "女";
           boolean bFull = false;
           
           public synchronized void put(String name, String sex)
           {
            if(bFull)
             try {
              wait();
             } catch (InterruptedException e1) {
              // TODO Auto-generated catch block
              e1.printStackTrace();
             }
            
            this.name = name;
            
            try{
             Thread.sleep(10);
            }
            catch(Exception e){
             System.out.println(e.getMessage());
            }
            
            this.sex = sex;
            
            bFull = true;
            notify();
           }
           
           public synchronized void get(){
            if(!bFull)
             try {
              wait();
             } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
             }
            System.out.println(name + "--->" + sex);
            
            bFull = false;
            notify();
           }
          }




          public class Productor implements Runnable {

           Record record = null;
           
           public Productor(Record record){
            this.record = record;
           }
           
           public void run(){
            int i = 0;
            
            while(true){
             if(i==0)
              record.put("陳陳陳", "男");
             else
              record.put("陳世美", "女");
             i = (i+1)%2;
            }
           }
          }

          public class Consumer implements Runnable {

           Record record = null;
           
           public Consumer(Record record){
            this.record = record;
           }
           
           public void run(){
            while(true){
             record.get();
            }
           }
          }

           public static void main(String[] args) {
            // TODO Auto-generated method stub

            Record record = new Record();
            new Thread(new Productor(record)).start();
            new Thread(new Consumer(record)).start();
           }



           

           


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 彰武县| 新田县| 新龙县| 垣曲县| 富平县| 社旗县| 怀仁县| 上虞市| 汕头市| 临高县| 邯郸市| 黄骅市| 温州市| 梨树县| 漯河市| 孙吴县| 望奎县| 澜沧| 延庆县| 阿克苏市| 类乌齐县| 陆丰市| 商丘市| 芜湖市| 聂荣县| 英山县| 肇东市| 日喀则市| 崇阳县| 吉木乃县| 延津县| 周至县| 梨树县| 那坡县| 和平区| 颍上县| 拉萨市| 秀山| 成安县| 朔州市| 新巴尔虎右旗|