
案例:主线程的执行需要等待子线程执行完,等各个线程执行完毕后,主线程做收尾的工作
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() {
@Override
public 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(); // 阻塞当前线程,直到计时器的值为0
System. out.println("主线程" + Thread.currentThread().getName() + "开始执行...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
service.shutdown();
}
}
}
案例2: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个线程都在操作CountDownLatch
System.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();
}
}
await方法的对比
线程一直阻塞的情况

到达时间后,就解除阻塞,并返回false

-1成功,返回true


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);
}
}

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");
}
}