Java同步工具类总结

先谈谈闭锁和栅栏的区别:

1.关键区别在于,全部线程必须同时到达栅栏位置,才能继续执行。html

2.闭锁用于等待某一个事件的发生,举例:CountDownLatch中await方法等待计数器为零时,全部事件才可继续执行。而栅栏是等待其余线程到位,全部事件才可继续下一步。例如:几个家庭决定在某个地方集合:“全部人6:00在麦当劳碰头,到了之后要等其余人,以后再讨论下一步要作的事情”。java

Semaphore(闭锁)

这个东西和以前的synchronized干的事差很少。
synchronized保证了,我管理的那部分代码同一时刻只有一个线程能访问
Semaphore保证了,我管理的那部分代码同一时刻最多能够有n个线程访问并发

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Semaphore;  
  
  
public class SemaphoreTest {  
    public static void main(String[] args) {  
        ExecutorService service = Executors.newCachedThreadPool();  
        final  Semaphore sp = new Semaphore(3);  
        for(int i=0;i<10;i++){  
            Runnable runnable = new Runnable(){  
                    public void run(){  
                    try {  
                        sp.acquire();  
                    } catch (InterruptedException e1) {  
                        e1.printStackTrace();  
                    }  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "进入,当前已有" + (3-sp.availablePermits()) + "个并发");  
                    try {  
                        Thread.sleep((long)(Math.random()*10000));  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "即将离开");                      
                    sp.release();  
                    //下面代码有时候执行不许确,由于其没有和上面的代码合成原子单元  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "已离开,当前已有" + (3-sp.availablePermits()) + "个并发");                      
                }  
            };  
            service.execute(runnable);            
        }  
    }  
  
  
}  

 运行结果以下:dom

线程pool-1-thread-2进入,当前已有2个并发
线程pool-1-thread-1进入,当前已有2个并发
线程pool-1-thread-3进入,当前已有3个并发
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有2个并发
线程pool-1-thread-4进入,当前已有3个并发
线程pool-1-thread-3即将离开
线程pool-1-thread-3已离开,当前已有2个并发
线程pool-1-thread-5进入,当前已有3个并发
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有2个并发
线程pool-1-thread-6进入,当前已有3个并发
线程pool-1-thread-4即将离开
线程pool-1-thread-4已离开,当前已有2个并发
线程pool-1-thread-7进入,当前已有3个并发
线程pool-1-thread-5即将离开
线程pool-1-thread-5已离开,当前已有2个并发
线程pool-1-thread-8进入,当前已有3个并发
线程pool-1-thread-8即将离开
线程pool-1-thread-9进入,当前已有3个并发
线程pool-1-thread-8已离开,当前已有3个并发
线程pool-1-thread-6即将离开
线程pool-1-thread-6已离开,当前已有2个并发
线程pool-1-thread-10进入,当前已有3个并发
线程pool-1-thread-10即将离开
线程pool-1-thread-10已离开,当前已有2个并发
线程pool-1-thread-7即将离开
线程pool-1-thread-7已离开,当前已有1个并发
线程pool-1-thread-9即将离开
线程pool-1-thread-9已离开,当前已有0个并发

 参考连接:http://www.cnblogs.com/nullzx/archive/2016/03/12/5270233.html ui

CountDownLatch (闭锁)

它保证了什么功能呢?其实和CycliBarrier也相似。线程

看下面这个图htm

这就是CycleBarrier,线程本身管理本身,你们看到人都到齐了,才继续走。


blog

这个是CountDownLatch,由他人来协调进度。事件

例如跑步的时候,有个裁判,等全部的人都到齐了,他吹哨,而后你们开始跑,等全部人都跑完了,他才公布成绩。get

import java.util.concurrent.CountDownLatch;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
  
public class CountdownLatchTest {  
  
  
    public static void main(String[] args) {  
        ExecutorService service = Executors.newCachedThreadPool();  
        final CountDownLatch cdOrder = new CountDownLatch(1);  
        final CountDownLatch cdAnswer = new CountDownLatch(3);        
        for(int i=0;i<3;i++){  
            Runnable runnable = new Runnable(){  
                    public void run(){  
                    try {  
                        System.out.println("线程" + Thread.currentThread().getName() +   
                                "正准备接受命令");                       
                        cdOrder.await();  
                        System.out.println("线程" + Thread.currentThread().getName() +   
                        "已接受命令");                                 
                        Thread.sleep((long)(Math.random()*10000));    
                        System.out.println("线程" + Thread.currentThread().getName() +   
                                "回应命令处理结果");                          
                        cdAnswer.countDown();                         
                    } catch (Exception e) {  
                        e.printStackTrace();  
                    }                 
                }  
            };  
            service.execute(runnable);  
        }         
        try {  
            Thread.sleep((long)(Math.random()*10000));  
          
            System.out.println("线程" + Thread.currentThread().getName() +   
                    "即将发布命令");                        
            cdOrder.countDown();  
            System.out.println("线程" + Thread.currentThread().getName() +   
            "已发送命令,正在等待结果");      
            cdAnswer.await();  
            System.out.println("线程" + Thread.currentThread().getName() +   
            "已收到全部响应结果");     
        } catch (Exception e) {  
            e.printStackTrace();  
        }                 
        service.shutdown();  
  
  
    }  
}  

 运行结果以下

线程pool-1-thread-3正准备接受命令
线程pool-1-thread-1正准备接受命令
线程pool-1-thread-2正准备接受命令
线程main即将发布命令
线程main已发送命令,正在等待结果
线程pool-1-thread-3已接受命令
线程pool-1-thread-2已接受命令
线程pool-1-thread-1已接受命令
线程pool-1-thread-3回应命令处理结果
线程pool-1-thread-1回应命令处理结果
线程pool-1-thread-2回应命令处理结果
线程main已收到全部响应结果

 

CountDownLatch里面有个计数器,初始值就是new countdownlatch时传入的

wait方法会一直等待,直到计数器的值变为0

coutdown方法可让计数器的值减一

 

CycleBarrier(栅栏)

CycleBarrier 能作到让n个线程互相等待,当n个线程都作到某一步后,再继续下一步。

例以下面的例子,5我的去旅游,设置abc三个中途节点,全部人都到达a以后在继续走向b,全部人都到达b,而后才继续走向c。

 

import java.util.concurrent.CyclicBarrier;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
  
public class CyclicBarrierTest {  
  
  
    public static void main(String[] args) {  
        ExecutorService service = Executors.newCachedThreadPool();  
        final  CyclicBarrier cb = new CyclicBarrier(3);  
        for(int i=0;i<3;i++){  
            Runnable runnable = new Runnable(){  
                    public void run(){  
                    try {  
                        Thread.sleep((long)(Math.random()*10000));    
                        System.out.println("线程" + Thread.currentThread().getName() +   
                                "即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                         
                        cb.await();  
                          
                        Thread.sleep((long)(Math.random()*10000));    
                        System.out.println("线程" + Thread.currentThread().getName() +   
                                "即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));  
                        cb.await();   
                        Thread.sleep((long)(Math.random()*10000));    
                        System.out.println("线程" + Thread.currentThread().getName() +   
                                "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));                       
                        cb.await();                       
                    } catch (Exception e) {  
                        e.printStackTrace();  
                    }                 
                }  
            };  
            service.execute(runnable);  
        }  
        service.shutdown();  
    }  
}  

运行结果以下:

 

线程pool-1-thread-2即将到达集合地点1,当前已有1个已经到达,正在等候
线程pool-1-thread-1即将到达集合地点1,当前已有2个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点1,当前已有3个已经到达,都到齐了,继续走啊
线程pool-1-thread-1即将到达集合地点2,当前已有1个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点2,当前已有2个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点2,当前已有3个已经到达,都到齐了,继续走啊
线程pool-1-thread-1即将到达集合地点3,当前已有1个已经到达,正在等候
线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候
线程pool-1-thread-3即将到达集合地点3,当前已有3个已经到达,都到齐了,继续走啊

 

Exchange(栅栏)

A线程有数据1,它须要与B线程的数据2作交换
B线程有数据2,它须要与A线程的数据1作交换

那么何时交换呢?得等AB都作好准备才行。

import java.util.concurrent.Exchanger;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
  
  
public class ExchangerTest {  
  
  
    public static void main(String[] args) {  
        ExecutorService service = Executors.newCachedThreadPool();  
        final Exchanger<String> exchanger = new Exchanger<String>();  
        service.execute(new Runnable(){  
            public void run() {  
                try {                 
  
  
                    String data1 = "zxx";  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                    "正在把数据" + data1 +"换出去");  
                    Thread.sleep((long)(Math.random()*10000));  
                    String data2 = (String)exchanger.exchange(data1);  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                    "换回的数据为" + data2);  
                }catch(Exception e){  
                      
                }  
            }     
        });  
        service.execute(new Runnable(){  
            public void run() {  
                try {                 
  
  
                    String data1 = "lhm";  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                    "正在把数据" + data1 +"换出去");  
                    Thread.sleep((long)(Math.random()*10000));                    
                    String data2 = (String)exchanger.exchange(data1);  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                    "换回的数据为" + data2);  
                }catch(Exception e){  
                      
                }                 
            }     
        });       
    }  
}  

 运行结果以下:

 

线程pool-1-thread-1正在把数据zxx换出去
线程pool-1-thread-2正在把数据lhm换出去
线程pool-1-thread-2换回的数据为zxx
线程pool-1-thread-1换回的数据为lhm
相关文章
相关标签/搜索