Java进阶——多线程相关,实际应用中的积累,持续更新

在这里插入图片描述


多线程相关

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() {

                @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名选手参加赛跑,选手需要等待裁判发送指令;裁判发送完指令后,需要等所有选手到达终点;所有选手到达终点后,裁判汇总成绩。

  • 主线程:裁判发指令,裁判等选手到达终点,到达终点后,汇总成绩;
  • 子线程:每个选手需要阻塞在裁判发指令之前,主线程发指令后,子线程继续运行;此时主线程阻塞,所有子线程结束后,主线程继续运行

实现的思路

  • 定义两个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个线程都在操作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();

    }
}

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");
    }
}
  • 12
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Arya's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值