激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - Java線程同步方法實例總結

Java線程同步方法實例總結

2021-05-28 13:08喜歡特別冷的冬天下著雪 Java教程

這篇文章主要介紹了Java線程同步方法,結合實例形式總結分析了Java線程同步、并發控制相關實現方法及操作注意事項,需要的朋友可以參考下

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

1. semaphore

 

1.1 二進制semaphore

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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個)并發嗎,則每一組也要進行同步,代碼修改如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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操作。下面模擬了一個開會的例子,只有當所有人員都到齊了,會議才能開始。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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程序設計有所幫助。

原文鏈接:https://blog.csdn.net/kkkkkxiaofei/article/details/19079259

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美特一级片 | 久久免费精品 | 一边吃奶一边摸下娇喘 | 一级国产电影 | 精品国产一区二区三区久久久蜜月 | 免费看成年人视频在线 | hd日本xxxx| www久久久久久 | 国产精品一区网站 | 日韩黄色av | 羞羞视频入口 | 国产乱乱视频 | 91久久久久久亚洲精品禁果 | 精品三区视频 | 欧美日韩国产一区二区三区在线观看 | 国产精品一区在线看 | 久久影院在线观看 | 精品一区二区三区欧美 | 国产1区在线观看 | 国产午夜三级一区二区三桃花影视 | 亚洲小视频在线观看,com | 久久久久亚洲国产精品 | 免费观看一级欧美大 | 久久69精品久久久久久国产越南 | 免费在线观看毛片视频 | 亚洲成人午夜精品 | 暖暖免费观看高清完整版电影 | 久久久午夜电影 | 亚洲第一视频 | 日本在线不卡一区二区 | 精品在线观看一区二区 | 悠悠成人资源亚洲一区二区 | 美国一级毛片片aa久久综合 | 国av在线| 中日韩乱码一二新区 | 日韩欧美精品电影 | 色女生影院 | 亚洲免费网站 | 久久综合一区 | 不卡一区二区三区视频 | 亚洲精品一区中文字幕 |