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

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


5.多個線程訪問共享對象和數據的方式

     如果每個線程執行的代碼相同,可以使用同一個Runnable對象,這個Runnable    

     對象中有那個共享數據。

 

     如果每個線程執行的代碼不同,這時候需要用不同的Runnable對象,這時可以將共   

     享數據封裝在另外一個對象中,然後將這個對象逐一傳遞給各個Runnable對象。每

     個線程對共享數據的操作方法也分配到那個對象身上去完成(把數據和數據操作封裝

     在一起),這樣容易實現針對該數據進行的各個操作的互斥和通信。

 

多個線程訪問共享對象和數據時,數據容易出現安全問題,因此,要注意加鎖。

 

6.線程池的概念:首先創建一些線程,它們的集合稱爲線程池,當服務器接受到一個客戶請求後,就從線程池中取出一個空閒的線程爲之服務,服務完後不關閉該線程,而是將該線程還回到線程池中。

 

在線程池的編程模式下,任務是提交給整個線程池,而不是直接交給某個線程,線程池在拿到任務後,它就在內部找有無空閒的線程,再把任務交給內部某個空閒的線程,若無空閒線程,則任務處於等待狀態。記住,任務是提交給整個線程池,一個線程同時只能執行一個任務,但可以同時向一個線程池提交多個任務。

 

Executors工廠類才產生線程池,相關方法(部分)如下:

static ExecutorService newCachedThreadPool()

     創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。

static ExecutorService newFixedThreadPool(int nThreads)

     創建一個可重用固定線程數的線程池。

static ScheduledExecutorServicenewScheduledThreadPool(int nThreads)

     創建一個可重用固定線程數的線程池,它可安排在給定延遲後運行或者定期地執行。

static ExecutorService newSingleThreadExecutor()

     創建一個只有一個線程的線程池,相當於newFixedThreadPool(1)

static ScheduledExecutorServicenewSingleThreadScheduledExecutor()

     創建一個單線程的線程池,它可安排在給定延遲後運行或者定期地執行。

 

ExecutorService 常用方法:

void execute(Runnable command)  執行給定的命令,此方法從父接口Executor中繼承而來。

void shutdown()

        執行以前提交的任務,但不接受新任務,任務執行完成後池中所有的線程都將死亡。

List<Runnable> shutdownNow()     試圖停止所有正在執行的活動任務,暫停處理

                                正在等待的任務,並返回等待執行的任務列表。

<T> Future<T> submit(Callable<T> task)

          提交一個返回值的任務用於執行,返回一個表示任務的結果的Future。

Future<?> submit(Runnable task)      提交一個 Runnable 任務用於執行,並返回一個

          表示該任務的 Future。Future無意義 。

 

Future類中常用方法:

V get()    等待計算完成,然後獲取其結果。

V get(long timeout, TimeUnit unit)

          最多等待爲使計算完成所給定的時間之後,獲取其結果(如果結果可用)。

boolean isCancelled()  如果在任務正常完成前將其取消,則返回 true。

boolean isDone()        如果任務已完成,則返回 true。

 

ScheduledExecutorService類繼承了ExecutorService接口,常用方法有:

<V> ScheduledFuture<V>  schedule(Callable<V> callable, longdelay, TimeUnit unit)

          創建並執行在給定延遲後啓用的ScheduledFuture。

ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit)

          創建並執行在給定延遲後啓用的一次性操作。

ScheduledFuture<?> scheduleAtFixedRate(Runnablecommand, long initialDelay, long period, TimeUnit unit)

          創建並執行一個在給定初始延遲後首次啓用的定期操作,後續操作具有給定的週期;也就是將在 initialDelay 後開始執行,然後在 initialDelay+period 後執行,接着在 initialDelay + 2 * period 後執行,依此類推。

ScheduledFuture<?> scheduleWithFixedDelay(Runnablecommand, long initialDelay, long delay, TimeUnit unit)

          創建並執行一個在給定初始延遲後首次啓用的定期操作,隨後,在每一次執行終止和下一次執行開始之間都存在給定的延遲。

 

示例:

public class TreadPoolTest {

    public static void main(String[] args) {

        //ExecutorServicepool=Executors.newFixedThreadPool(3);

        //ExecutorServicepool=Executors.newCachedThreadPool();

        ExecutorServicepool=Executors.newSingleThreadExecutor();

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

            final int a=i;

            pool.execute(new Runnable() {

                public void run() {

                   

                    for(int j=0;j<5;j++){

                        try {

                            Thread.currentThread().sleep(500);

                        } catch (InterruptedException e) {

                            e.printStackTrace(); }

            System.out.println("thread:"+a+"  loop:"+j);}}});}

            Future<String>fut=pool.submit(new Callable<String>() {

                public String call()throws Exception {

                System.out.println("call is running……");

                return "hello,java";}});

        System.out.println(fut.get());}}

 

7.CompletionService用於提交一組Callable任務,其take方法返回任務中已完成的一個Callable任務對應的Future對象。

示例:

        ExecutorService service= Executors.newFixedThreadPool(3);

        CompletionService<Integer>completionService =

                   new ExecutorCompletionService<Integer>(service);

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

            completionService.submit(new Callable<Integer>(){

                public Integer call()throws Exception {

                    Integer a = 0;

                    try {

                        a = new Random().nextInt(10);

                        System.out.println("product a:" + a);

 

                        Thread.sleep((long) (a * 100));

                    } catch (Exception e) {

                    }

                    return a;

                }

            });

        }

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

            Future<Integer> f = completionService.take();

            System.out.println("get a:" + f.get());

        }

以上代碼基本上遵循返回一個數,得到一個數的趨勢。

8.讀寫鎖:

示例:

public class LockTest {

    static Source source=new Source();

    public static void main(String []a){

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

            new Thread(new Runnable() {            

                public void run() {

                    source.setA();}}).start();

            new Thread(new Runnable() {            

                public void run() {

                    source.getA();}}).start();}}}

 

class Source{

    int a=0;

    ReadWriteLock  rwl=new ReentrantReadWriteLock();

    void   setA(){

        rwl.writeLock().lock();

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

" 準備產生a……");

        try {

            Thread.currentThread().sleep(1000);

        } catch (Exception e) {

            e.printStackTrace();}

        a=new Random().nextInt();

        System.out.println(a);

        System.out.println("已經產生a");

        rwl.writeLock().unlock();}

    void  getA(){

        rwl.readLock().lock();

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

" 準備得到a……");

        try {

            Thread.currentThread().sleep(1000);

        } catch (Exception e) {

            e.printStackTrace();}

        System.out.println(a);

        System.out.println("已經得到a");

        rwl.readLock().unlock();}}

通常在釋放鎖時,代碼放在finally中,避免拋出異常時,鎖爲釋放資源。

 

讀寫鎖應用之緩存系統:

public class CacheDemo {

    privateMap<String, Object> cache = new HashMap<String, Object>();

    public staticvoid main(String[] args) {            }

    privateReadWriteLock rwl = new ReentrantReadWriteLock();

    public  Object getData(String key){

        rwl.readLock().lock();

        Object value = null;

        try{

            value= cache.get(key);

            if(value== null){

                rwl.readLock().unlock();

                rwl.writeLock().lock();

                try{

                    if(value==null){

                        value = "aaaa";//實際是去queryDB();

                    }

                }finally{

                    rwl.writeLock().unlock();

                }

                rwl.readLock().lock();

            }

        }finally{

            rwl.readLock().unlock();

        }

        return value;

    }

}






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

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

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