Semaphore
基本使用
synchronized 可以起到锁的作用,但某个时间段内,只能有一个线程允许执行
Semaphore(信号量)用来限制能同时访问共享资源的线程上限(不是资源数),非重入锁
不像之前的reentrantlock那些是独占锁。Semaphore是共享资源有多个,允许多个线程占有,只是希望对数量进行把控
构造方法:
-
public Semaphore(int permits)
:permits 表示许可线程的数量(state) -
public Semaphore(int permits, boolean fair)
:fair 表示公平性,如果设为 true,下次执行的线程会是等待最久的线程
常用API:
-
public void acquire()
:表示获取许可 -
public void release()
:表示释放许可,acquire() 和 release() 方法之间的代码为同步代码
public static void main(String[] args) { // 1.创建Semaphore对象 Semaphore semaphore = new Semaphore(3); // 2. 10个线程同时运行 for (int i = 0; i < 10; i++) { new Thread(() -> { try { // 3. 获取许可 semaphore.acquire(); sout(Thread.currentThread().getName() + " running..."); Thread.sleep(1000); sout(Thread.currentThread().getName() + " end..."); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 4. 释放许可 semaphore.release(); } }).start(); } }
应用
线程数等于资源数就很合适
-
单机版限流,仅仅限制线程数,不是限制资源数。
-
简单连接池。对比享元模式的wait、notify。性能和可读性更好
CountDown
倒计时锁
为什么不用join
join也可以使主线程等待3个线程结束再执行。
join属于比较底层的api用起来比较繁琐,比如将来肯定是使用线程池,线程都是不断再运行的,肯定不能让某一个线程结束。
基本使用
CountDownLatch:计数器,用来进行线程同步协作,等待所有线程完成倒计时计时
构造器:
-
public CountDownLatch(int count)
:初始化唤醒需要的 down 几步
常用API:
-
public void await()
:让当前线程等待,必须 down 完初始化的数字才可以被唤醒,否则进入无限等待【计时(数)器走完】 -
public void countDown()
:计数器进行减 1(down 1)
应用:同步等待多个 Rest 远程调用结束
// LOL 10人进入游戏倒计时 public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(10); ExecutorService service = Executors.newFixedThreadPool(10); String[] all = new String[10]; Random random = new Random(); for (int j = 0; j < 10; j++) { int finalJ = j;//常量 service.submit(() -> { for (int i = 0; i <= 100; i++) { Thread.sleep(random.nextInt(100)); //随机休眠 all[finalJ] = i + "%"; System.out.print("\r" + Arrays.toString(all)); // \r代表覆盖 } latch.countDown(); }); } latch.await(); System.out.println("\n游戏开始"); service.shutdown(); } /* [100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%] 游戏开始