黑馬程序員_java基礎加強7_多線程加強

---------------------- android培訓java培訓、期待與您交流! ----------------------




2. 定時器的使用:

Timer相關用法:

Timer()    創建一個新計時器。

Timer(boolean isDaemon)  創建一個新計時器,可以指定其相關的線程作爲守護程序運行。

Timer(String name) 創建一個新計時器,其相關的線程具有指定的名稱。

Timer(String name, boolean isDaemon)   創建一個新計時器,其相關的線程具有指定的名稱,並且可以指定作爲守護程序運行。

 

void cancel()   終止此計時器,丟棄所有當前已安排的任務。

int purge()   從此計時器的任務隊列中移除所有已取消的任務。

void schedule(TimerTask task, Date time)   安排在指定的時間執行指定的任務。

void schedule(TimerTask task, Date firstTime, longperiod)

          安排指定的任務在指定的時間開始進行重複的固定延遲執行。

void schedule(TimerTask task, long delay)    安排在指定延遲後執行指定的任務。

void schedule(TimerTask task, long delay, long period)

          安排指定的任務從指定的延遲後開始進行重複的固定延遲執行。

void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)

          安排指定的任務在指定的時間開始進行重複的固定速率執行。

void scheduleAtFixedRate(TimerTask task, long delay,long period)

          安排指定的任務在指定的延遲後開始進行重複的固定速率執行。

 

說明:每隔兩秒輸出booming,然後隔4秒輸出booming,再隔兩秒輸出booming,然後隔4秒輸出booming,

如此交替輸出。

public class TraditionalTimerTest {

    private static int count = 0;

    public static void main(String[] args) {

        new Timer().schedule(new MyTimerTask(), 2000);

    }

    static class MyTimerTask extends TimerTask{

        public void run() {

            count = (count+1)%2;

            System.out.println("bombing!");

            System.out.println(new Date());

            new Timer().schedule(new MyTimerTask(),1000+1000*count);

        }

    }

}

3.wait、notify、notifyAll這三個方法必須由同步監視器對象來調用。

Notify是隨機喚醒一個線程。

在沒有被通知、中斷或超時的情況下,線程還可以喚醒一個所謂的虛假喚醒(spurious wakeup)。雖然這種情況在實踐中很少發生,但是應用程序必須通過以下方式防止其發生,即對應該導致該線程被提醒的條件進行測試,如果不滿足該條件,則繼續等待。換句話說,等待應總是發生在循環中,如下面的示例:

synchronized (obj) {

while (<condition does nothold>)

obj.wait(timeout);

... // Perform actionappropriate to condition

     }

子線程循環10次,接着主線程循環100次,再子線程循環10次,接着主線程循環100次,如此重複50次。注意編程構造方法。

public class TraditionalThreadCommunication {

    public static void main(String[] args) {     

        final Business business = new Business();

        new Thread(

                new Runnable() {                 

                    @Override

                    public void run() {

                   

                        for(int i=1;i<=50;i++){

                            business.sub(i);

                        }                      

                    }

                }

        ).start();

        for(int i=1;i<=50;i++){

            business.main(i);

        }

    }

}

//封裝資源

  class Business {

      private boolean bShouldSub = true;

      public synchronized void sub(int i){

          while(!bShouldSub){

              try {

                this.wait();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

          }

            for(int j=1;j<=10;j++){

            System.out.println("sub thread : " + j + ",loop of " + i);

            }

          bShouldSub = false;

          this.notify();

      }  

      public synchronized void main(int i){

            while(bShouldSub){

                try {

                    this.wait();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

            for(int j=1;j<=100;j++){

            System.out.println("main thread: " + j + ",loop of " + i);

            }

            bShouldSub = true;

            this.notify();

      }

  }

上例類設計原則:要上鎖的代碼放在資源內部,不是線程代碼中。

 

4.線程範圍類的數據共享類ThreadLocal:用於實現線程內的數據共享,即多個模塊在同一個線程中運行時要共享一份線程內的數據。如:購物車中,支付模塊,購買物品模塊共享同一個購物車實例。在每個購物車中數據都不相同,一個購物車相當於啓動一個線程。

示例:

以下程序中,模塊A和B都用於打印各自線程內的數據。每個線程內產生的數據都不相同。

import java.util.Random;

public class TreadScopeDataShare {

staticThreadLocal<ThreadData> threadLocal=

                                       new ThreadLocal<ThreadData>();

    public static void main(String[] args) {

        for(int i=0;i<3;i++){

            new Thread(new Runnable(){

                @Override

                public void run() {

                    int a=new Random().nextInt(100);

                    ThreadData user=new ThreadData();

                    user.setName("name"+a);

                    user.setAge(a);

                    threadLocal.set(user);

                    System.out.println(a +" is put into

                             "+Thread.currentThread().getName());

                    new ModuleA(threadLocal).printUser();

                    new ModuleB(threadLocal).printUser();

                    }   }).start();}}}

class ThreadData{

    private String name;

    private int age;

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public int getAge() {return age;}

    public void setAge(int age) {this.age = age;}}

//模塊用於輸出變量

class ModuleA{

    ThreadLocal<ThreadData> a=new ThreadLocal<ThreadData>();

    publicModuleA(ThreadLocal<ThreadData> a) {

        this.a=a;}

    public void printUser(){

        ThreadData user=a.get();

        System.out.println(Thread.currentThread().getName()+"  

                        ModuleA print  name:"+

                       user.getName()+"  age:"+user.getAge());}}

 

class ModuleB{

    ThreadLocal<ThreadData> a=new ThreadLocal<ThreadData>();

    publicModuleB(ThreadLocal<ThreadData> a) {

        this.a=a;}

    public void printUser(){

        ThreadData user=a.get();

        System.out.println(Thread.currentThread().getName()+"

                          ModuleB print  name:"+

                          user.getName()+"  age:"+user.getAge());}

在實際開發中, 通常將一個ThreadLocal綁定到一個線程中,即線程數據類的設計方法如下:

class ThreadData{

    private static ThreadLocal<ThreadData> map =

                                       new ThreadLocal<ThreadData>();

    private String name;

    private int age;

    private ThreadData() {   }

    public static ThreadDatagetThreadInstance() {

        ThreadDatainstance = map.get();

        if (instance == null) {

            instance = new ThreadData();

            map.set(instance);       }

        return instance;  }

    public String getName() {return name;}

    public void setName(String name) { this.name = name;}

    public int getAge() {    return age;}

    public void setAge(int age) {   this.age = age;}}





---------------------- android培訓java培訓、期待與您交流! ----------------------

詳細請查看:http://edu.csdn.net/heima

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章