引出
Java多线程——如何控制线程顺序执行,如何控制线程同时执行
如何控制线程执行顺序?
问题:现在有 T1、T2、T3 三个线程,你怎样保证 执行顺序是t3—> t2 —> t1 ?
public class App8 {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(() -> {
System.out.println("执行t1");
}, "t1");
Thread t2 = new Thread(() -> {
System.out.println("执行t2");
}, "t2");
Thread t3 = new Thread(() -> {
System.out.println("执行t3");
}, "t3");
t3.start();
//t.join()方法只会使主线程(或者说调用t.join()的线程)进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程。
t3.join();
t2.start();
t2.join();
t1.start();
t1.join();
}
}
多个线程在某一时刻同时开始执行?
countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。 倒计时闭锁。
CountDownLatch
是 Java 标准库中提供的一个同步工具类,用于在多线程编程中协调多个线程的执行顺序。它的作用是允许一个或多个线程等待其他线程完成操作后再继续执行,用于控制线程之间的同步。
CountDownLatch
的核心思想是:一个线程(或多个线程)等待其他线程完成某个操作后,再继续执行。
- CountDownLatch
- 1、作用: 主要用于控制一个或多个线程等待其他线程完成一组操作,然后再继续执行
- 2、await()方法则使调用该方法的线程处于等待状态,一般是主线程调用。
- 3、countDown()方法每次都会使计数器减一,减为0时处于阻塞等待的主线程将会被唤醒。
public class App9 {
/**
* CountDownLatch
* 1、作用: 主要用于控制一个或多个线程等待其他线程完成一组操作,然后再继续执行
* 2、await()方法则使调用该方法的线程处于等待状态,一般是主线程调用。
* 3、countDown()方法每次都会使计数器减一,减为0时处于阻塞等待的主线程将会被唤醒。
* 需求:三局对战都胜利,才胜利
*/
public static void main(String[] args) throws InterruptedException {
String[] country = {"对战1","对战2","对战3"};
CountDownLatch countDownLatch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(()->{
// 执行任务
System.out.println(Thread.currentThread().getName() + "执行完毕");
// 任务完成,减少计数
countDownLatch.countDown();
},country[i]).start();
}
// 等待所有任务完成
countDownLatch.await();
System.out.println("取得胜利!!!");
}
}
Redis冲冲冲——缓存三兄弟:缓存击穿、穿透、雪崩
缓存击穿
缓存击穿:redis中没有,但是数据库有
顺序:先查缓存,判断缓存是否存在;如果缓存存在,直接返回数据;如果缓存不存在,則查询数据库,将数据库的数据存入到缓存
解决方案:将热点数据设置过期时间长一点;针对数据库的热点访问方法上分布式锁;
缓存穿透
缓存穿透:redis中没有,数据库也没有
解决方案:
(1)将不存在的key,在redis设置值为null;
(2)使用布隆过滤器;
原理:https://zhuanlan.zhihu.com/p/616911933
布隆过滤器:
如果确认key不存在于redis中,那么就一定不存在;
它说key存在,就有可能存在,也可能不存在! (误差)
布隆过滤器
1、根据配置类中的 key的数量 ,误差率,计算位图数组【二维数组】
2、通过布隆过滤器存放key的时候,会计算出需要多少个hash函数,由hash函数算出多少个位图位置需要设定为1
3、查询时,根据对应的hash函数,判断对应的位置值是否都为1;如果有位置为0,则表示key一定不存在于该redis服务器中;如果全部位置都为1,则表示key可能存在于redis服务器中;
缓存雪崩
缓存雪崩:
Redis的缓存雪崩是指当Redis中大量缓存数据同时失效或者被清空时,大量的请求会直接打到数据库上,导致数据库瞬时压力过大,甚至宕机的情况。
造成缓存雪崩的原因主要有两个:
1.相同的过期时间:当Redis中大量的缓存数据设置相同的过期时间时,这些数据很可能会在同一时间点同时失效,导致大量请求直接打到数据库上。
2.缓存集中失效:当服务器重启、网络故障等因素导致Redis服务不可用,且缓存数据没有自动进行容错处理,当服务恢复时大量的数据同时被重新加载到缓存中,也会导致大量请求直接打到数据库上。
预防缓存雪崩的方法主要有以下几种:
1.设置不同的过期时间:可以将缓存数据的过期时间分散开,避免大量缓存数据在同一时间点失效。
2.使用加锁:可以将所有请求都先进行加锁操作,当某个请求去查询数据库时,如果还没有加载到缓存中,则只让单个线程去执行加载操作,其他线程等待该线程完成后再次进行判断,避免瞬间都去访问数据库从而引起雪崩。
3.提前加载预热:在系统低峰期,可以提前将部分热点数据加载到缓存中,这样可以避免在高峰期缓存数据失效时全部打到数据库上。
4.使用多级缓存:可以在Redis缓存之上再使用一层缓存,例如本地缓存等,当Redis缓存失效时,还能够从本地缓存中获取数据,避免直接打到数据库上。
本地缓存:ehcache oscache spring自带缓存 持久层框架的缓存
总结
Java多线程——如何控制线程顺序执行,如何控制线程同时执行