目录
- 多线程相关
- CountDownLatch
- 赛跑的案例
- countDownLatch.await(300, TimeUnit.SECONDS);
- Java其他进阶
- Map的put方法
- 只放一个元素的集合
多线程相关
CountDownLatch
案例:主线程的执行需要等待子线程执行完,等各个线程执行完毕后,主线程做收尾的工作
- 初始化一个:final CountDownLatch latch = new CountDownLatch(3);
- 线程池中的子线程调用 countDown方法进行减1;
- 主线程启动后,等待子线程不断减1,直到为0后,主线程继续往下执行;
package com.tianju.myTest;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CountdownLatchTest1 {public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(3);final CountDownLatch latch = new CountDownLatch(3);for (int i = 0; i < 3; i++) {Runnable runnable = new Runnable() {@Overridepublic void run() {try {System. out.println("子线程" + Thread.currentThread().getName() + "开始执行");Thread. sleep((long) (Math. random() * 10000));System. out.println("子线程" + Thread.currentThread().getName() + "执行完成");latch.countDown(); // 当前线程调用此方法,则计数减一} catch (InterruptedException e) {e.printStackTrace();}}};service.execute(runnable);}try {System. out.println("主线程" + Thread.currentThread().getName() + "等待子线程执行完成..." );latch.await(); // 阻塞当前线程,直到计时器的值为0System. out.println("主线程" + Thread.currentThread().getName() + "开始执行...");} catch (InterruptedException e) {e.printStackTrace();}finally {service.shutdown();}}
}
赛跑的案例
案例2:4名选手参加赛跑,选手需要等待裁判发送指令;裁判发送完指令后,需要等所有选手到达终点;所有选手到达终点后,裁判汇总成绩。
- 主线程:裁判发指令,裁判等选手到达终点,到达终点后,汇总成绩;
- 子线程:每个选手需要阻塞在裁判发指令之前,主线程发指令后,子线程继续运行;此时主线程阻塞,所有子线程结束后,主线程继续运行
实现的思路
- 定义两个CountDownLatch,一个为1,一个为4;
- CountDownLatch(1),用来控制等待裁判指令,主线程先休眠,让出资源,让子线程获得cpu资源,子线程通过await 阻塞;
- 主线程休眠结束后,对1进行-1,然后await 4 阻塞,触发子线程,子线程继续运行;
- 子线程在运行过程中对于4 进行-1,等到值为0时,触发主线程的await 4 阻塞;
- 主线程继续运行,裁判进行成绩的汇总
package com.tianju.myTest;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// https://www.cnblogs.com/tstd/p/4987935.html
public class CountdownLatchTest2 {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final CountDownLatch cdOrder = new CountDownLatch(1);final CountDownLatch cdAnswer = new CountDownLatch(4);for (int i = 0; i < 4; 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(); // 进行-1操作,4个线程都在操作CountDownLatchSystem.out.println("cdAnswer---->:"+cdAnswer);} 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("所有选手都到达终点" );System. out.println("裁判" + Thread.currentThread ().getName() + "汇总成绩排名" );} catch (Exception e) {e.printStackTrace();}service.shutdown();}
}
countDownLatch.await(300, TimeUnit.SECONDS);
await方法的对比
- 没有设置时间,会一直阻塞,直到countdown为0;
- 设置了时间,在超过这个时间后,解除阻塞,返回false;
线程一直阻塞的情况
到达时间后,就解除阻塞,并返回false
-1成功,返回true
Java其他进阶
Map的put方法
- Map 的 put 方法其实是有返回值的
package com.tianju.myTest;import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;/*** hashMap 的 put 方法其实是有返回值的*/
public class ConHashMap {public static void main(String[] args) {ConcurrentHashMap<Object, Object> concurrentHashMap = new ConcurrentHashMap<>();// 如果有了键为 pet,还能往里面放concurrentHashMap.put("pet", 567);Object put = concurrentHashMap.put("pet", "task");System.out.println(put);if (put!=null){System.out.println("======== current key used! ========");}System.out.println(concurrentHashMap);HashMap<Object, Object> hashMap = new HashMap<>();hashMap.put("pet", 123);Object pet = hashMap.put("pet", 561);System.out.println(pet);System.out.println(hashMap);}
}
只放一个元素的集合
- 基于内存或者业务的考虑,有时候集合只放一个元素,可以用collections下面的singleton集合
package com.tianju.myTest;import java.util.Collections;
import java.util.List;/*** 只能存放一个元素的 List,不会造成内存空间的浪费*/
public class SingletonListTest {public static void main(String[] args) {String s = "hello, singleton";List<String> list = Collections.singletonList(s);list.add("second element");}
}