亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Java線程同步方法實例總結

2024-07-14 08:42:10
字體:
來源:轉載
供稿:網友

本文實例講述了Java線程同步方法。分享給大家供大家參考,具體如下:

1. Semaphore

1.1 二進制Semaphore

Semaphore算是比較高級點的線程同步工具了,在許多其他語言里也有類似的實現。Semaphore有一個最大的好處就是在初始化時,可以顯式的控制并發數。其內部維護這一個c計數器,當計數器小于等于0時,是不允許其他線程訪問并發區域的,反之則可以,因此,若將并發數設置為1,則可以確保單一線程同步。下面的例子模擬多線程打印,每個線程提交打印申請,然后執行打印,最后宣布打印結束,代碼如下:

import java.util.concurrent.Semaphore;public class Program{    public static void main(String[] agrs){        PrintQueue p=new PrintQueue();        Thread[] ths=new Thread[10];        for(int i=0;i<10;i++){            ths[i]=new Thread(new Job(p),"Thread"+i);        }        for(int i=0;i<10;i++){            ths[i].start();        }    }}class PrintQueue{    private Semaphore s;    public PrintQueue(){        s=new Semaphore(1);//二進制信號量    }    public void printJob(Object document){        try{            s.acquire();            long duration=(long)(Math.random()*100);            System.out.printf("線程名:%s 睡眠:%d",Thread.currentThread().getName(),duration);            Thread.sleep(duration);        }        catch(InterruptedException e){            e.printStackTrace();        }        finally{            s.release();        }    }}class Job implements Runnable{    private PrintQueue p;    public Job(PrintQueue p){        this.p=p;    }    @Override    public void run(){        System.out.printf("%s:正在打印一個任務/n ",Thread.currentThread().getName());        this.p.printJob(new Object());        System.out.printf("%s:文件已打印完畢/n ",Thread.currentThread().getName());    }}

執行結果如下:

 Thread0:正在打印一個任務
 Thread9:正在打印一個任務
 Thread8:正在打印一個任務
 Thread7:正在打印一個任務
 Thread6:正在打印一個任務
 Thread5:正在打印一個任務
 Thread4:正在打印一個任務
 Thread3:正在打印一個任務
 Thread2:正在打印一個任務
 Thread1:正在打印一個任務
 線程名:Thread0 睡眠:32  Thread0:文件已打印完畢
 線程名:Thread9 睡眠:44  Thread9:文件已打印完畢
 線程名:Thread8 睡眠:45  Thread8:文件已打印完畢
 線程名:Thread7 睡眠:65  Thread7:文件已打印完畢
 線程名:Thread6 睡眠:12  Thread6:文件已打印完畢
 線程名:Thread5 睡眠:72  Thread5:文件已打印完畢
 線程名:Thread4 睡眠:98  Thread4:文件已打印完畢
 線程名:Thread3 睡眠:58  Thread3:文件已打印完畢
 線程名:Thread2 睡眠:24  Thread2:文件已打印完畢
 線程名:Thread1 睡眠:93  Thread1:文件已打印完畢

可以看到,所有線程提交打印申請后,按照并發順序一次執行,沒有任何并發沖突,誰先獲得信號量,誰就先執行,其他剩余線程均等待。這里面還有一個公平信號與非公平信號之說:基本上java所有的多線程工具都支持初始化的時候指定一個布爾變量,true時表明公平,即所有處于等待的線程被篩選的條件為“誰等的時間長就選誰進行執行”,有點first in first out的感覺,而false時則表明不公平(默認是不non-fairness),即所有處于等待的線程被篩選執行是隨機的。這也就是為什么多線程往往執行順序比較混亂的原因。

1.2 多重并發控制

若將上面的代碼改為s=new Semaphore(3);//即讓其每次可以并發3條線程,則輸出如下:

Thread0:正在打印一個任務
 Thread9:正在打印一個任務
 Thread8:正在打印一個任務
 Thread7:正在打印一個任務
 Thread6:正在打印一個任務
 Thread5:正在打印一個任務
 Thread3:正在打印一個任務
 Thread4:正在打印一個任務
 Thread2:正在打印一個任務
 Thread1:正在打印一個任務
 線程名:Thread9 睡眠:26線程名:Thread8 睡眠:46線程名:Thread0 睡眠:79  Thread9:文件已打印完畢
 線程名:Thread7 睡眠:35  Thread8:文件已打印完畢
 線程名:Thread6 睡眠:90  Thread7:文件已打印完畢
 線程名:Thread5 睡眠:40  Thread0:文件已打印完畢
 線程名:Thread3 睡眠:84  Thread5:文件已打印完畢
 線程名:Thread4 睡眠:13  Thread4:文件已打印完畢
 線程名:Thread2 睡眠:77  Thread6:文件已打印完畢
 線程名:Thread1 睡眠:12  Thread1:文件已打印完畢
   Thread3:文件已打印完畢
   Thread2:文件已打印完畢

很明顯已經并發沖突了。若要實現分組(每組3個)并發嗎,則每一組也要進行同步,代碼修改如下:

import java.util.concurrent.Semaphore;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Program{    public static void main(String[] agrs){        PrintQueue p=new PrintQueue();        Thread[] ths=new Thread[10];        for(int i=0;i<10;i++){            ths[i]=new Thread(new Job(p),"Thread"+i);        }        for(int i=0;i<10;i++){            ths[i].start();        }    }}class PrintQueue{    private Semaphore s;    private boolean[] freePrinters;    private Lock lock;    public PrintQueue(){        s=new Semaphore(3);//二進制信號量        freePrinters=new boolean[3];        for(int i=0;i<3;i++){            freePrinters[i]=true;        }        lock=new ReentrantLock();    }    public void printJob(Object document){        try{            s.acquire();            int printerIndex=getIndex();                long duration=(long)(Math.random()*100);                System.out.printf("線程名:%s 睡眠:%d/n",Thread.currentThread().getName(),duration);                Thread.sleep(duration);                freePrinters[printerIndex]=true;//恢復信號,供下次使用        }        catch(InterruptedException e){            e.printStackTrace();        }        finally{            s.release();        }    }    //返回一個內部分組后的同步索引    public int getIndex(){        int index=-1;        try{            lock.lock();            for(int i=0;i<freePrinters.length;i++){                if(freePrinters[i]){                    freePrinters[i]=false;                    index=i;                    break;                }            }     }     catch(Exception e){         e.printStackTrace();     }     finally{         lock.unlock();     }     return index;    }}class Job implements Runnable{    private PrintQueue p;    public Job(PrintQueue p){        this.p=p;    }    @Override    public void run(){        System.out.printf("%s:正在打印一個任務/n ",Thread.currentThread().getName());        this.p.printJob(new Object());        System.out.printf(" %s:文件已打印完畢/n ",Thread.currentThread().getName());    }}

其中getIndex()方法主要為了維護內部分組后(支持并發3個)組內數據的同步(用lock來同步)。

輸出如下:

 Thread0:正在打印一個任務
 Thread9:正在打印一個任務
 Thread8:正在打印一個任務
 Thread7:正在打印一個任務
 Thread6:正在打印一個任務
 Thread5:正在打印一個任務
 Thread4:正在打印一個任務
 Thread3:正在打印一個任務
 Thread2:正在打印一個任務
 Thread1:正在打印一個任務
 線程名:Thread0 睡眠:82  打印機:0號
線程名:Thread8 睡眠:61  打印機:2號
線程名:Thread9 睡眠:19  打印機:1號
  Thread9:文件已打印完畢
 線程名:Thread7 睡眠:82  打印機:1號
  Thread8:文件已打印完畢
 線程名:Thread6 睡眠:26  打印機:2號
  Thread0:文件已打印完畢
 線程名:Thread5 睡眠:31  打印機:0號
  Thread6:文件已打印完畢
 線程名:Thread4 睡眠:44  打印機:2號
  Thread7:文件已打印完畢
 線程名:Thread3 睡眠:54  打印機:1號
  Thread5:文件已打印完畢
 線程名:Thread2 睡眠:48  打印機:0號
  Thread4:文件已打印完畢
 線程名:Thread1 睡眠:34  打印機:2號
  Thread3:文件已打印完畢
   Thread2:文件已打印完畢
   Thread1:文件已打印完畢

2. CountDownLatch

CountDownLatch同樣也是支持多任務并發的一個工具。它主要用于“等待多個并發事件”,它內部也有一個計數器,當調用await()方法時,線程處于等待狀態,只有當內部計數器為0時才繼續(countDown()方法來減少計數),也就說,假若有一個需求是這樣的:主線程等待所有子線程都到達某一條件時才執行,那么只需要主線程await,然后在啟動每個子線程的時候進行countDown操作。下面模擬了一個開會的例子,只有當所有人員都到齊了,會議才能開始。

import java.util.concurrent.CountDownLatch;public class Program{    public static void main(String[] agrs){        //開啟可容納10人的會議室        VideoConference v=new VideoConference(10);        new Thread(v).start();        //參與人員陸續進場        for(int i=0;i<10;i++){            Participant p=new Participant(i+"號人員",v);            new Thread(p).start();        }    }}class VideoConference implements Runnable{    private CountDownLatch controller;    public VideoConference(int num){        controller=new CountDownLatch(num);    }    public void arrive(String name){        System.out.printf("%s 已經到達!/n",name);        controller.countDown();        System.out.printf("還需要等 %d 個成員!/n",controller.getCount());    }    @Override    public void run(){        try{            System.out.printf("會議正在初始化...!/n");            controller.await();            System.out.printf("所有人都到齊了,開會吧!/n");        }        catch(InterruptedException e){            e.printStackTrace();        }    }}class Participant implements Runnable{    private VideoConference conference;    private String name;    public Participant(String name,VideoConference conference){        this.name=name;        this.conference=conference;    }    @Override    public void run(){        long duration=(long)(Math.random()*100);        try{            Thread.sleep(duration);            conference.arrive(this.name);     }     catch(InterruptedException e){     }    }}

輸出:

會議正在初始化...!
0號人員 已經到達!
還需要等 9 個成員!
1號人員 已經到達!
還需要等 8 個成員!
9號人員 已經到達!
還需要等 7 個成員!
4號人員 已經到達!
還需要等 6 個成員!
8號人員 已經到達!
還需要等 5 個成員!
5號人員 已經到達!
還需要等 4 個成員!
6號人員 已經到達!
還需要等 3 個成員!
3號人員 已經到達!
還需要等 2 個成員!
7號人員 已經到達!
還需要等 1 個成員!
2號人員 已經到達!
還需要等 0 個成員!
所有人都到齊了,開會吧!

3. Phaser

import java.util.concurrent.Phaser;import java.util.concurrent.TimeUnit;import java.util.List;import java.util.ArrayList;import java.io.File;import java.util.Date;public class Program{    public static void main(String[] agrs){        Phaser phaser=new Phaser(3);        FileSearch system=new FileSearch("C://Windows", "log",phaser);        FileSearch apps=new FileSearch("C://Program Files","log",phaser);        FileSearch documents=new FileSearch("C://Documents And Settings","log",phaser);        Thread systemThread=new Thread(system,"System");        systemThread.start();        Thread appsThread=new Thread(apps,"Apps");        appsThread.start();        Thread documentsThread=new Thread(documents, "Documents");        documentsThread.start();        try {            systemThread.join();            appsThread.join();            documentsThread.join();            } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("Terminated: "+ phaser.isTerminated());    }}class FileSearch implements Runnable{    private String initPath;    private String end;    private List<String> results;    private Phaser phaser;    public FileSearch(String initPath,String end,Phaser phaser){        this.initPath=initPath;        this.end=end;        this.results=new ArrayList<String>();        this.phaser=phaser;    }    private void directoryProcess(File file){        File[] files=file.listFiles();        if(files!=null){            for(int i=0;i<files.length;i++){                if(files[i].isDirectory()){                    directoryProcess(files[i]);                }                else{                    fileProcess(files[i]);                }            }        }    }    private void fileProcess(File file){        if(file.getName().endsWith(end)){            results.add(file.getAbsolutePath());        }    }    private void filterResults(){        List<String> newResults=new ArrayList<String>();        long actualDate=new Date().getTime();        for(int i=0;i<results.size();i++){            File file=new File(results.get(i));            long fileDate=file.lastModified();            if(actualDate-fileDate<TimeUnit.MILLISECONDS.convert(1,TimeUnit.DAYS)){                newResults.add(results.get(i));            }        }        results=newResults;    }    private boolean checkResults(){        if(results.isEmpty()){            System.out.printf("%s: Phase %d: 0 results./n",Thread.currentThread().getName(),phaser.getPhase());            System.out.printf("%s: Phase %d: End./n",Thread.currentThread().getName(),phaser.getPhase());            phaser.arriveAndDeregister();        }        else{            System.out.printf("%s: Phase %d: %d results./n",Thread.currentThread().getName(),phaser.getPhase(),results.size());             phaser.arriveAndAwaitAdvance();            return true;        }    }    private void showInfo() {        for (int i=0; i<results.size(); i++){            File file=new File(results.get(i));            System.out.printf("%s: %s/n",Thread.currentThread().getName(),file.getAbsolutePath());        }        phaser.arriveAndAwaitAdvance();    }    @Override    public void run(){        File file=new File(initPath);        if(file.isDirectory()){            directoryProcess(file);        }        if(!checkResults()){            return;        }        filterResults();        if(!checkResults()){            return;        }        showInfo();        phaser.arriveAndDeregister();        System.out.printf("%s: Work completed./n",Thread.currentThread().getName());    }}

運行結果:

Apps: Phase 0: 4 results.
System: Phase 0: 27 results.

希望本文所述對大家java程序設計有所幫助。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一区深夜视频| 亚洲www在线观看| 国产91在线播放| 欧美激情亚洲综合一区| 欧美成人剧情片在线观看| 国产精品福利在线观看| 精品香蕉在线观看视频一| 亚洲精品久久久久久久久| 亚洲专区国产精品| 亚洲字幕一区二区| 国产精欧美一区二区三区| 欧美日韩国产丝袜另类| 亚洲成人网久久久| 精品国产欧美一区二区三区成人| 欧美日韩亚洲网| 精品亚洲一区二区三区在线播放| 日韩欧美国产激情| 国产激情久久久久| 91精品国产色综合久久不卡98| 国产精品青青在线观看爽香蕉| 亚洲天堂网在线观看| 4k岛国日韩精品**专区| 欧美日韩国产va另类| 日韩中文字幕精品视频| 欧美成人免费视频| yw.139尤物在线精品视频| 国产午夜精品视频免费不卡69堂| 亚洲影院色无极综合| 精品久久久一区二区| 亚洲第一黄色网| 久久99久久99精品免观看粉嫩| 欧美成人午夜影院| 欧美裸体xxxxx| 在线日韩日本国产亚洲| 日韩av在线导航| 国产日韩视频在线观看| 欧美亚州一区二区三区| 成人高h视频在线| 亚洲国产成人久久综合| 精品少妇一区二区30p| 91tv亚洲精品香蕉国产一区7ujn| 亚洲欧美福利视频| 亚洲精品美女在线观看| 午夜精品久久久久久99热| 亚洲成人黄色在线| 日韩在线资源网| 色www亚洲国产张柏芝| 日韩精品视频免费专区在线播放| 久久大大胆人体| 国产狼人综合免费视频| 国产成人午夜视频网址| 国产精品成人在线| 日韩欧美在线视频免费观看| 国产精品免费小视频| 在线看片第一页欧美| 国产成人精品视| 日本高清不卡在线| 超碰91人人草人人干| 国产精品直播网红| 在线观看久久久久久| 日韩美女激情视频| 久久99久久亚洲国产| 亚洲人午夜精品免费| www高清在线视频日韩欧美| 中文字幕亚洲综合久久筱田步美| 97久久超碰福利国产精品…| 欧美激情一区二区三区久久久| 日韩精品视频在线观看免费| 国产日韩欧美视频| 欧美激情2020午夜免费观看| 国产欧美日韩专区发布| 成人国产精品一区| 久久777国产线看观看精品| 亚洲第一区第一页| 久久久久久成人精品| 欧美xxxx18性欧美| 久久久久久噜噜噜久久久精品| 亚洲自拍欧美色图| 亚洲天堂精品在线| 日韩成人黄色av| 热久久美女精品天天吊色| 欧美日韩人人澡狠狠躁视频| 欧美性xxxx极品高清hd直播| 亚洲精品美女在线观看| 久久在线精品视频| 亚洲直播在线一区| 欧美午夜精品久久久久久人妖| 亚洲精品久久久久国产| 91情侣偷在线精品国产| 亚洲一区二区中文| 亚洲精品福利在线| 久久偷看各类女兵18女厕嘘嘘| 91免费精品国偷自产在线| 日韩成人中文字幕| 97视频国产在线| 欧美成人精品xxx| 热久久美女精品天天吊色| 日韩在线一区二区三区免费视频| 久久精品一区中文字幕| 亚洲欧美综合图区| 国产亚洲精品久久久优势| 激情亚洲一区二区三区四区| 日韩电影免费观看中文字幕| 91精品国产色综合久久不卡98| 久久精品视频在线播放| xvideos亚洲| 久久影视免费观看| 91免费精品国偷自产在线| 欧美性猛交xxxx乱大交3| 日韩欧美一区二区三区久久| 最近2019中文字幕mv免费看| 视频直播国产精品| 久久精品亚洲一区| 中文字幕国产亚洲2019| 亚洲人成电影在线观看天堂色| 欧美午夜无遮挡| 久久久黄色av| 青青草一区二区| 大量国产精品视频| 亚洲精品久久久久久久久久久久久| 福利一区视频在线观看| 亚洲男人第一av网站| 国产成人a亚洲精品| 国产日本欧美一区二区三区在线| 国产精品久久久久影院日本| 亚洲精品成a人在线观看| 亚洲人成电影在线播放| 欧美电影在线观看完整版| 欧美黑人国产人伦爽爽爽| 国模gogo一区二区大胆私拍| 在线免费观看羞羞视频一区二区| 在线观看欧美成人| 国产香蕉97碰碰久久人人| 久久免费精品日本久久中文字幕| 69久久夜色精品国产7777| 欧美最猛性xxxxx免费| 色悠久久久久综合先锋影音下载| 精品成人国产在线观看男人呻吟| 亚洲欧美综合另类中字| 亚洲综合色av| 国产日韩精品电影| 久久亚洲精品一区二区| 国产精品福利在线| 欧洲永久精品大片ww免费漫画| 亚洲丝袜一区在线| 日韩电影大片中文字幕| 欧美成人黄色小视频| 正在播放欧美一区| 亚洲a级在线观看| 欧美裸体视频网站| 欧亚精品在线观看| 国内精品视频一区| 国产精品久久久久久亚洲调教| 日韩精品福利在线| 中文字幕欧美精品在线| 亚洲国产精品成人av| 欧洲亚洲免费视频| 国产精品高清网站| 欧美色欧美亚洲高清在线视频| 亚洲美腿欧美激情另类| 黄色成人在线播放| 午夜精品久久久久久99热软件| 国产精品免费观看在线| 欧美成人中文字幕在线|