<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

    多線程實(shí)用操作方法大全

    Posted on 2009-07-19 23:41 Gavin.lee 閱讀(852) 評(píng)論(0)  編輯  收藏 所屬分類: 多線程

     線程控制基本方法
      方    法                             功    能
    isAlive()                     判斷線程是否還“活”著,即當(dāng)前run線程是否還未終止。
    getPriority()               獲得線程的優(yōu)先級(jí)數(shù)值
    setPriority()               設(shè)置線程的優(yōu)先級(jí)數(shù)值
    Thread.sleep()           將當(dāng)前線程睡眠指定毫秒數(shù)
    join()                         調(diào)用某線程的該方法,將當(dāng)前線程與該線程“合并”,即等待該線程結(jié)束,再恢復(fù)當(dāng)前線程的運(yùn)行。
    yield()                       讓出CPU,當(dāng)前線程進(jìn)入就緒隊(duì)列等待調(diào)度。
    wait()                       當(dāng)前線程進(jìn)入對(duì)象的wait pool。
    notify()/notifyAll()      喚醒對(duì)象的wait pool中的一個(gè)/所有等待線程。

    run()和start()

    這兩個(gè)方法應(yīng)該都比較熟悉,把需要并行處理的代碼放在run()方法中,start()方法啟動(dòng)線程將自動(dòng)調(diào)用 run()方法,這是由Java的內(nèi)存機(jī)制規(guī)定的。并且run()方法必須是public訪問權(quán)限,返回值類型為void。

    isAlive方法實(shí)例:

    package com.Gavin.createthread;

    public class TestIsAlive {

        
    public static void main(String[] args) {
            Thread6 t6 
    = new Thread6("t6");
            t6.start();
            
            
    for(int i = 0; i < 50; i++{
    //            System.out.println(Thread.currentThread().getName());    //主線程
                System.out.println("t6's name:" + t6.getName());
            }

        }


    }


    class Thread6 extends Thread {
        
    public Thread6(String string) {
            
    super(string);
        }

        
    public void run() {
            System.out.println(
    "thread is alive:" + Thread.currentThread().isAlive());
            
            
    for(int i = 0; i < 50; i++{
                System.out.println(
    "subThread:" + i);
            }

        }

    }


    interrupt/sleep方法:
                可以調(diào)用Thread的靜態(tài)方法: public static void sleep(long millis) throws InterruptedException
                    使得當(dāng)前線程休眠(暫時(shí)停止執(zhí)行millis毫秒)。
                由于是靜態(tài)方法,sleep可以由類名直接調(diào)用:Thread.sleep(…)

    使當(dāng)前線程(即調(diào)用該方法的線程)暫停執(zhí)行一段時(shí)間,讓其他線程有機(jī)會(huì)繼續(xù)執(zhí)行,但它并不釋放對(duì)象鎖。也就是如果有Synchronized同步塊,其他線程仍然不同訪問共享數(shù)據(jù)。注意該方法要捕獲異常

    比如有兩個(gè)線程同時(shí)執(zhí)行(沒有Synchronized),一個(gè)線程優(yōu)先級(jí)為MAX_PRIORITY,另一個(gè)為MIN_PRIORITY,如果沒有 Sleep()方法,只有高優(yōu)先級(jí)的線程執(zhí)行完成后,低優(yōu)先級(jí)的線程才能執(zhí)行;但當(dāng)高優(yōu)先級(jí)的線程sleep(5000)后,低優(yōu)先級(jí)就有機(jī)會(huì)執(zhí)行了。

    總之,sleep()可以使低優(yōu)先級(jí)的線程得到執(zhí)行的機(jī)會(huì),當(dāng)然也可以讓同優(yōu)先級(jí)、高優(yōu)先級(jí)的線程有執(zhí)行的機(jī)會(huì)。

    package com.Gavin.createthread;

    import java.util.Date;

    public class TestInterrupt {    
        
    public static void main(String[] args) {
            Thread1 t 
    = new Thread1();
            t.start();
            
    /**
             * api中稱:中斷線程
             * Thread1線程與主線程開始并發(fā),主線程讓出10s,
             * 然后調(diào)用interrupt強(qiáng)行終止Thread1線程
             
    */

            
    try {
                Thread.sleep(
    10000);
            }
     catch(InterruptedException e) {            
            }

            
            t.interrupt();
        }

    }


    class Thread1 extends Thread {
        
    public void run() {
            
    while (true{
                System.out.println(
    "===" + new Date()+ "===");
                
    try {
                    sleep(
    1000);
                }
     catch (InterruptedException e) {
                    
    return;
                }

            }

        }

    }

    停止線程的方法中,stop最強(qiáng)暴,其次便是interrupte,這兩種都是不提倡的,推薦的方法是通過flag標(biāo)志來終止線程,例如:

    package com.Gavin.createthread;
    public class TestShutDown {    
        
    public static void main(String[] args) {    
            Thread5 t5 
    = new Thread5();
            Thread t 
    = new Thread(t5);
            t.start();        
            
    for(int i = 0; i < 100; i++{
                System.out.println(
    "main thread i:" + i);
            }

            System.out.println(
    "main thread is over");
            
    /**
             * 通過操作flag標(biāo)志來關(guān)閉線程,推薦使用
             
    */

            t5.shutDown();        
    //        t.stop();    //太暴力,不推薦
        }

    }

    class Thread5 implements Runnable {
        
    private boolean flag = true;    
        
    public void run() {
            
    int i = 0;
            
    while(flag) {
                System.out.println(
    "value:" + i++);
            }
            
        }
        
        
    public void shutDown() {
            flag 
    = false;
        }

    }



    join方法:
                合并某個(gè)線程,,join()方法使調(diào)用該方法的線程在此之前執(zhí)行完畢,也就是等待調(diào)用該方法的線程執(zhí)行完畢后再往下繼續(xù)執(zhí)行。注意該方法也要捕獲異常。

    package com.Gavin.createthread;

    public class TestJoin {
        
    public static void main(String[] args) {
            
    //指定新的線程對(duì)象,并通過super指向Thread,指定線程名稱
            Thread2 t = new Thread2("Thread2 ");        
            t.start();
            
    /**
             * api中稱:等待該線程終止。
             * 當(dāng)線程啟動(dòng)后,原本線程是會(huì)與主線程并發(fā)執(zhí)行
             * 當(dāng)調(diào)用了join方法后,意味著Thread2線程將會(huì)與主線程合并
             * 所以,需要等待Thread2線程執(zhí)行完畢,合并后,主線程才會(huì)繼續(xù)執(zhí)行
             
    */

            
    try {
                t.join();
            }
     catch (InterruptedException e) {
            }

            
    for(int i = 0; i <= 10; i++{
                System.out.println(
    "i am main thread " + i);
            }

        }

    }


    class Thread2 extends Thread {
        Thread2(String string) 
    {
            
    super(string);
        }
        
        
    public void run() {
            
    for(int i = 0; i <= 10; i++{
                System.out.println(
    "i am " + getName() + i);
                
    try {
                    
    /**
                     * api中稱:在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),
                     * 此操作受到系統(tǒng)計(jì)時(shí)器和調(diào)度程序精度和準(zhǔn)確性的影響 
                     
    */

                    sleep(
    1000);
                }
     catch (InterruptedException e) {
                    
    return;
                }

            }

        }
        
    }

    yield方法:
                暫時(shí)讓出CPU,給其他線程執(zhí)行的機(jī)會(huì),它與sleep()類似,只是不能由用戶指定暫停多長時(shí)間,并且yield()方法只能讓同優(yōu)先級(jí)的線程有執(zhí)行的機(jī)會(huì)。

    package com.Gavin.createthread;

    public class TestYield {
        
    public static void main(String[] args) {
            Thread3 t 
    = new Thread3("t");
            Thread3 tt 
    = new Thread3("tt");
            t.start();
            tt.start();
        }

    }

    class Thread3 extends Thread {
        Thread3(String string) 
    {
            
    super(string);
        }

        
    public void run () {
            
    for(int i = 0; i < 100; i++{
                System.out.println(getName() 
    + ":" + i);
                
    if(i % 10 == 0{
                    
    /**
                     * api中稱:暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。
                     * 注:暫停時(shí)間片不定,只是到條件即暫時(shí)讓出cpu
                     
    */

                    yield();
                }

            }

        }

    }


    setPriority():

    package com.Gavin.createthread;

    public class TestPriority {

        
    public static void main(String[] args) {
            Thread t1 
    = new Thread(new T1());
            Thread t2 
    = new Thread(new T2());
            
    /**
             * 未設(shè)置優(yōu)先級(jí)的,t1,t2將幾乎擁有均等的時(shí)間片,交互執(zhí)行
             * 但是當(dāng)設(shè)置優(yōu)先級(jí)后,t1會(huì)擁有更長時(shí)間片。甚至t1在搶奪的時(shí)間片內(nèi)已執(zhí)行完。
             
    */

            t1.setPriority(Thread.NORM_PRIORITY 
    + 3);
            
            t1.start();
            t2.start();
        }


    }


    class T1 implements Runnable {
        
    public void run() {
            
    for(int i = 0; i < 200; i++{
                System.out.println(
    "T1:" + i);
            }

        }
        
    }
     

    class T2 implements Runnable {
        
    public void run() {
            
    for(int i = 0; i < 200; i++{
                System.out.println(
    "T2:" + i);
            }

        }

        
    }

     


    關(guān)鍵字Synchronized

    這個(gè)關(guān)鍵字用于保護(hù)共享數(shù)據(jù),當(dāng)然前提是要分清哪些數(shù)據(jù)是共享數(shù)據(jù)。每個(gè)對(duì)象都有一個(gè)鎖標(biāo)志,當(dāng)一個(gè)線程訪問該對(duì)象時(shí),被Synchronized修飾的數(shù)據(jù)將被“上鎖”,阻止其他線程訪問。當(dāng)前線程訪問完這部分?jǐn)?shù)據(jù)后釋放鎖標(biāo)志,其他線程就可以訪問了。
     

    //同步鎖
    public class TestSync implements Runnable {
        Timer timer 
    = new Timer();    
        
    public static void main(String[] args) {
            TestSync test 
    = new TestSync();
            Thread t1 
    = new Thread(test);
            Thread t2 
    = new Thread(test);

            
    //t1.setName("t1");
            
    //t2.setName("t2");
            t1.start();
            t2.start();
        }

        
    public void run() {
            timer.add(Thread.currentThread().getName());
        }

    }

    class Timer{
        
    private static int num = 0;

        
    //synchronized 鎖定當(dāng)前對(duì)象
        public synchronized void add(String name) {
            
    //synchronized(this) {
                num++;
                
    try    {
                    Thread.sleep(
    1);
                }
     catch (InterruptedException e){

                }

                System.out.println(name 
    + ",你是第" + num + "個(gè)使用timer的線程");
            
    //}
        }

    }

     

    注意以下這個(gè)例子

    public ThreadTest implements Runnable 
        
    public synchronized void run()
            
    for(int i=0;i<10;i++
            System.out.println(
    " " + i); 
            }
     
        }
     
        
    public static void main(String[] args) 
            Runnable r1 
    = new ThreadTest(); 
            Runnable r2 
    = new ThreadTest(); 
            Thread t1 
    = new Thread(r1); 
            Thread t2 
    = new Thread(r2); 
            t1.start(); 
            t2.start(); 
        }

    }

    結(jié)果: 0 0 1 2 3 4 1 5 2 6 3 7 4 8 9 5 6 7 8 9 ;(不同對(duì)象)
    以上這段程序中的 i 變量并不是共享數(shù)據(jù),這個(gè)程序中的t1,t2分別是兩個(gè)對(duì)象(r1,r2)的線程。JAVA是面向?qū)ο蟮某绦蛟O(shè)計(jì)語言,不同的對(duì)象的數(shù)據(jù)是不同的,r1,r2有各自的run()方法,而synchronized使同一個(gè)對(duì)象的多個(gè)線程,在某個(gè)時(shí)刻只有其中的一個(gè)線程可以訪問這個(gè)對(duì)象的synchronized數(shù)據(jù)。

    當(dāng)把代碼改成如下:Synchronized關(guān)鍵字才會(huì)起作用

    Runnable r = new ThreadTest();

    Thread t1 = new Thread(r);

    Thread t2 = new Thread(r);

    t1.start();

    t2.start();

    synchronized 導(dǎo)致的死鎖問題:


    //死鎖典型:哲學(xué)家吃飯問題
    public class TestDeadLock implements Runnable{
        
    public int flag = 1;
        
    static Object o1 = new Object();
        
    static Object o2 = new Object();
        
    public void run() {
            System.out.println(
    "flag=" + flag);
            
    if(flag == 1{
                
    synchronized(o1) {
                    
    try    {
                        Thread.sleep(
    500);
                    }
    catch (InterruptedException e)    {
                        e.printStackTrace();
                    }

                    
    synchronized(o2) {
                        System.out.println(
    "1");
                    }

                }

            }


            
    if(flag == 0{
                
    synchronized(o2) {
                    
    try    {
                        Thread.sleep(
    500);
                    }
    catch (InterruptedException e)    {
                        e.printStackTrace();
                    }

                    
    synchronized(o1) {
                        System.out.println(
    "0");
                    }


                }

            }
        
        }


        
    public static void main(String[] args) {
            TestDeadLock td1 
    = new TestDeadLock();
            TestDeadLock td2 
    = new TestDeadLock();
            td1.flag 
    = 1;
            td2.flag 
    = 0;
            Thread t1 
    = new Thread(td1);
            Thread t2 
    = new Thread(td2);
            t1.start();
            t2.start();
        }

    }



    wait()和notify()、notifyAll()

    這三個(gè)方法用于協(xié)調(diào)多個(gè)線程對(duì)共享數(shù)據(jù)的存取,所以必須在Synchronized語句塊內(nèi)使用這三個(gè)方法。前面說過Synchronized這個(gè)關(guān)鍵字用于保護(hù)共享數(shù)據(jù),阻止其他線程對(duì)共享數(shù)據(jù)的存取。但是這樣程序的流程就很不靈活了,如何才能在當(dāng)前線程還沒退出Synchronized數(shù)據(jù)塊時(shí)讓其他線程也有機(jī)會(huì)訪問共享數(shù)據(jù)呢?此時(shí)就用這三個(gè)方法來靈活控制。

    wait()方法使當(dāng)前線程暫停執(zhí)行并釋放對(duì)象鎖標(biāo)志,讓其他線程可以進(jìn)入Synchronized數(shù)據(jù)塊,當(dāng)前線程被放入對(duì)象等待池中。當(dāng)調(diào)用 notify()方法后,將從對(duì)象的等待池中移走一個(gè)任意的線程并放到鎖標(biāo)志等待池中,只有

    鎖標(biāo)志等待池中的線程能夠獲取鎖標(biāo)志;如果鎖標(biāo)志等待池中沒有線程,則notify()不起作用。

    notifyAll()則從對(duì)象等待池中移走所有等待那個(gè)對(duì)象的線程并放到鎖標(biāo)志等待池中。

    注意 這三個(gè)方法都是java.lang.Ojbect的方法!

    主站蜘蛛池模板: 成人免费无码H在线观看不卡| 免费**毛片在线播放直播| 亚洲国产成人久久精品动漫| 亚洲毛片αv无线播放一区| 成人精品国产亚洲欧洲| 无码人妻一区二区三区免费手机| 亚洲国产女人aaa毛片在线| 成人妇女免费播放久久久| 亚洲美女在线国产| 羞羞漫画在线成人漫画阅读免费| 永久黄网站色视频免费直播 | 小草在线看片免费人成视久网| 久久久久亚洲爆乳少妇无| 日本在线观看免费高清| 99在线观看免费视频| 国产在线19禁免费观看| 亚洲av成人一区二区三区在线播放| 精品四虎免费观看国产高清午夜| 好男人视频社区精品免费| 亚洲精品无码不卡| 美女在线视频观看影院免费天天看| 亚洲无线观看国产精品| 抽搐一进一出gif免费视频| 久久99亚洲综合精品首页| jizz在线免费播放| 亚洲乳大丰满中文字幕| 免费精品久久天干天干| 亚洲国产电影av在线网址| 污污污视频在线免费观看| 24小时日本在线www免费的| 亚洲人成图片网站| 日本免费大黄在线观看| 亚洲精品国产成人99久久| 99精品视频在线视频免费观看| 久久精品蜜芽亚洲国产AV | 国内一级一级毛片a免费| 亚洲日韩AV一区二区三区中文| 女人被弄到高潮的免费视频| 亚洲AV无码成人网站在线观看| 免费国产在线观看| jizz免费一区二区三区|