各种同步控制工具的使用

简介:

Semaphore

概述

共享锁,运行多个线程同时临界区

主要接口

public void acquire()
public void acquireUninterruptibly()
public boolean tryAcquire()
public boolean tryAcquire(long timeout, TimeUnit unit)
public void release() 

使用

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
public class SemaphoreDemo {
    private static final int THREAD_COUNT = 3;
    private static ExecutorService threadPool = Executors
        .newFixedThreadPool(THREAD_COUNT);
 
    private static Semaphore s = new Semaphore(1);
    public static void main(String[] args) {
        for(int i=0;i<3;i++)
        {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName()+"start data");
                        Thread.sleep(2000);
                        s.acquire();
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName()+"save data");
                        s.release();
                        System.out.println(Thread.currentThread().getName()+"release data");
                        Thread.sleep(2000);
                        System.out.println(Thread.currentThread().getName()+"end data");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        threadPool.shutdown();
    }
}

 最后得出一个比较有意思的结论:Semaphore 像是一个共享的屋子,这个屋子里面只能有一定的人数,这个人数是所有人可以看到的,甚至与release()这个方法,可以被别的线程进行调用,

一般使用acquire()  与release() 这个之间的代码只能有固定数量的线程存在,当然这种是当前线程进行获取和释放

ReadWriteLock

概述

ReadWriteLock是JDK5中提供的读写分离锁 

读-读不互斥:读读之间不阻塞。
读-写互斥:读阻塞写,写也会阻塞读。
写-写互斥:写写阻塞。 

主要使用

private static ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
private static Lock readLock = readWriteLock.readLock();
private static Lock writeLock = readWriteLock.writeLock(); 

这个类如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void run() { 
               //isRead自定义变量(判断这个线程是读还是写)
               if (isRead) { 
                       //获取读锁 
                       myLock.readLock().lock(); 
                       System.out.println("读");
                       //释放读锁 
                       myLock.readLock().unlock(); 
               } else { 
                       //获取写锁 
                       myLock.writeLock().lock(); 
                       //执行现金业务 
                               System.out.println("写");
                       //释放写锁 
                       myLock.writeLock().unlock(); 
               } 
       }                                         

 CountDownLatch 

概述:

static final CountDownLatch end = new CountDownLatch(10);
end.countDown();   //这个方法是子线程作完作业之后,调用的
end.await(); //主线等待指定数量的子线程完成作业,当所有子线程完成之后,主线程自动激活执行

 

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
public class CountDownLatchDemo {
    private static CountDownLatch countDownLatch=new CountDownLatch(10);
    public static void main(String[] args) {
        for(int i=0;i<10;i++)
        {
           new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"work");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    countDownLatch.countDown();
 
                }
            }).start();
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    countDownLatch.await();
                    System.out.println(Thread.currentThread().getName()+"主线程start");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"main1").start();
    }
}

 CyclicBarrier 

概述

 

 

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
public class CyclicBarrierDemo {
    public static class Soldier implements Runnable{
        private  String name;
        private final CyclicBarrier cyclicBarrier;
 
        public Soldier(String name,CyclicBarrier c) {
            this.name = name;
            this.cyclicBarrier=c;
        }
 
        @Override
        public void run() {
              try{
                  //等待所有士兵到齐
                  System.out.println(name +"报道");
                  cyclicBarrier.await();
                    dowork();
                  //等待所有士兵完成工作
                  cyclicBarrier.await();
 
              }
              catch (Exception e)
              {
                  e.printStackTrace();
              }
        }
        public void dowork()
        {
                System.out.println(name +"完成任务");
        }
    }
 
    public static class BarrierRun implements Runnable{
        boolean flag;
        int  number;
        public BarrierRun(boolean flag, int number) {
            this.flag = flag;
            this.number = number;
        }
 
        @Override
        public void run() {
            if(!flag)
            {
                System.out.println("士兵集合完毕");
                flag=true;
                System.out.println("开始执行任务");
            }
            else{
                System.out.println("任务完成");
 
            }
        }
    }
    public static void main(String[] args) {
        final  int N =10;
 
        CyclicBarrier barrier =new CyclicBarrier(N,new BarrierRun(false,N));
        System.out.println("集合队伍");
        for(int i=0;i<N;i++)
        {
            new Thread(new Soldier("士兵"+i,barrier)).start();
        }
    }
}

 每次CyclicBarrier 调用await()方法之后,都会等待所有的子线程,之后执行CyclicBarrier 的Runnable的方法

 

LockSupport

概述

unpark函数可以先于park调用。比如线程B调用unpark函数,给线程A发了一个“许可”,那么当线程A调用park时,它发现已经有“许可”了,那么它会马上再继续运行。

park和unpark的灵活之处

上面已经提到,unpark函数可以先于park调用,这个正是它们的灵活之处。

一个线程它有可能在别的线程unPark之前,或者之后,或者同时调用了park,那么因为park的特性,它可以不用担心自己的park的时序问题













本文转自xsster51CTO博客,原文链接:http://blog.51cto.com/12945177/1930152 ,如需转载请自行联系原作者




相关文章
|
2月前
|
安全 Java 网络安全
com.jcraft是什么工具
【6月更文挑战第28天】com.jcraft是什么工具
79 0
|
3月前
|
JSON 数据格式
介绍几种使用工具
介绍几种使用工具
|
11月前
|
SQL OceanBase
obdumper` 工具
obdumper` 工具
288 1
|
10月前
|
程序员
这些工具也太好用了吧
这些工具也太好用了吧
28 0
|
11月前
|
文字识别 数据安全/隐私保护
这5款好用的工具你用过吗?
人类与99%的动物之间最大差别在于是否会运用工具,借助好的工具,能提升几倍的工作效率。
132 0
|
Windows 容器 开发工具
|
Web App开发 监控 网络协议
|
Web App开发 安全