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

          java 線程

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

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

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

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



          public class ThreadDemo2 {

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

          }



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

          如下列所示

          //實(shí)現(xiàn)多線程方法二:實(shí)現(xiàn)Runnable接口,重載run函數(shù),
          //大多數(shù)情況下,如果只想重寫 run() 方法,而不重寫其他 Thread 方法,
          //那么應(yīng)使用 Runnable 接口。這很重要,
          //因?yàn)槌浅绦騿T打算修改或增強(qiáng)類的基本行為,否則不應(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類的一個(gè)實(shí)例
            Thread thread = new Thread(testThread);//創(chuàng)建一個(gè)Thread類的實(shí)例
            thread.start();//使線程進(jìn)入runnable狀態(tài)
            
            while(true){
             System.out.println("main thread is running...");
            }
           }


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


          如下列所示:
          //四個(gè)售票窗口售同一中車票,總共有100張,要求這四個(gè)售票多線程進(jìn)行
          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)建了四個(gè)線程,每個(gè)線程調(diào)用了同一各TicketRunnable對(duì)象中run方法,
            //訪問(wèn)的是同一個(gè)對(duì)象中的變量tickets,從而滿足了我們的要求。
            //實(shí)現(xiàn)Runnable接口適合多個(gè)相同的程序代碼訪問(wèn)處理同一資源
            TicketRunnable ticketrunnable = new TicketRunnable();
            new Thread(ticketrunnable).start();
            new Thread(ticketrunnable).start();
            new Thread(ticketrunnable).start();
            new Thread(ticketrunnable).start();
           }
          }

          而繼承繼承Thread類,并重載run方法不能達(dá)到此目的
          如下所示:
          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){
            //我們希望的是四個(gè)線程共售100,我們創(chuàng)建四個(gè)線程
            //但結(jié)果與我們希望的相反,各個(gè)線程各售100張票
            new TicketThread().start();
            new TicketThread().start();
            new TicketThread().start();
            new TicketThread().start();
            
          //  如果我們象下面這樣寫的話,只有一個(gè)線程在售票,沒(méi)有實(shí)現(xiàn)四個(gè)線程并發(fā)售票
          //  TicketThread ticketThread = new TicketThread();
          //  ticketThread.start();
          //  ticketThread.start();
          //  ticketThread.start();
          //  ticketThread.start();
           }
          }

          3.后臺(tái)線程

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

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

          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--);
              }
             }
           }
          }

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

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

          public class TicketSynch implements Runnable{
           
           private int tickets = 100;
           String str = new String("");//此對(duì)象放在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--);
              }
             }
            }
           }

          }

          但是 同步以犧牲程序的性能為代價(jià)

          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)建了四個(gè)線程,每個(gè)線程調(diào)用了同一各TicketRunnable對(duì)象中run方法,
            //訪問(wèn)的是同一個(gè)對(duì)象中的變量tickets,從而滿足了我們的要求。
            //實(shí)現(xiàn)Runnable接口適合多個(gè)相同的程序代碼訪問(wèn)處理同一資源
            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();// 這個(gè)線程調(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();//這個(gè)線程調(diào)用同步函數(shù)
           }

           

          7. 線程間通訊

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

          notify:?jiǎn)拘淹粚?duì)象監(jiān)視器中調(diào)用wait的第一個(gè)線程。類似飯館有一個(gè)空位置后通知所有等待就餐顧客中的第一位可以入座的情況

          notifyAll:?jiǎn)拘淹粚?duì)象監(jiān)視器中調(diào)用wait的所有線程,具有最高優(yōu)先級(jí)的程序先被喚醒并執(zhí)行。

          以上三個(gè)方法只能在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();
           }



           

           


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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 尚志市| 方城县| 班戈县| 资阳市| 佳木斯市| 泌阳县| 海南省| 太白县| 甘德县| 甘洛县| 炎陵县| 兴文县| 沾化县| 望奎县| 西丰县| 桃园市| 广丰县| 乐东| 兰考县| 历史| 凤山县| 台安县| 原阳县| 贵定县| 井陉县| 铜陵市| 济源市| 大方县| 伊宁市| 巍山| 迁安市| 丹东市| 孝义市| 依安县| 泰州市| 朔州市| 太谷县| 永胜县| 简阳市| 东乡县| 莱州市|