2024年Java最新Day302&303&304,月薪30K必须掌握的开源项目Java中SPI机制

最后

如果觉得本文对你有帮助的话,不妨给我点个赞,关注一下吧!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

public class Imooccahe3<A,V> implements Computable<A,V> {

private final HashMap<A,V> cache = new HashMap<A,V>();

private final Computable<A,V> c;//装饰者模式接口类

public Imooccahe3(Computable<A, V> c) {

this.c = c;

}

@Override

public synchronized V compute(A args) throws Exception {

System.out.println(“进入缓存机制”);

V result = cache.get(args);

if (result==null){

//通过装饰者模式计算

result = c.compute(args);

cache.put(args,result);

}

return result;

}

//主函数

public static void main(String[] args) throws Exception {

//构造函数传入我们具体进行计算的实现类

Imooccahe3<String, Integer> imooccahe3 = new Imooccahe3<>(new ExpensiveFunction());

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe3.compute(“666”);

System.out.println(“第一次计算结果:”+result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe3.compute(“667”);

System.out.println(“第二次计算结果:”+result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe3.compute(“666”);

System.out.println(“第三次计算结果:”+result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

}

}

image-20210618221158111

那么如何优化这个情况呢?并发容器


5、使用线程安全的map

通过使用ConcurrentHashMap来替换之前的HashMap

image-20210618221601005

  • 缺点

image-20210618221659461

  • 问题图示

image-20210618222402122

image-20210618222239965

那么我们如何避免重复计算呢????

使用Future和Callable


6、使用Future&Callable避免重复计算

image-20210618222625176

  • 代码实现

利用Future避免重复计算

/******

@author 阿昌

@create 2021-06-18 21:10


  •  利用Future避免重复计算
    

*/

public class Imooccahe5<A, V> implements Computable<A, V> {

private final ConcurrentHashMap<A, Future> cache = new ConcurrentHashMap<>();

private final Computable<A, V> c;//装饰者模式接口类

public Imooccahe5(Computable<A, V> c) {

this.c = c;

}

@Override

public V compute(A args) throws Exception {

Future future = cache.get(args);

if (future == null) {

Callable callable = new Callable() {

@Override

public V call() throws Exception {

return c.compute(args);

}

};

FutureTask futureTask = new FutureTask<>(callable);

//如果future等于null,那将计算完的结果赋给future返回

future = futureTask;

cache.put(args, futureTask);//在计算之前,放入缓存

System.out.println(“从FutureTask调用计算函数”);

futureTask.run();//开始计算调用方法

}

//如果此时future没值,那么他就会阻塞去等有值了再get

//因为ConcurrentHashMap保证了可见性,会看见有线程正在做计算

return future.get();

}

//主函数

public static void main(String[] args) throws Exception {

//构造函数传入我们具体进行计算的实现类

Imooccahe5<String, Integer> imooccahe5 = new Imooccahe5<>(new ExpensiveFunction());

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe5.compute(“666”);

System.out.println(“第一次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe5.compute(“667”);

System.out.println(“第二次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe5.compute(“666”);

System.out.println(“第三次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

}

}

image-20210618225716705

  • 依然存在问题

image-20210618225817090

image-20210618225939292

  • 解决方案

通过putIfAbsentput当这个值不存在的时候,返回放之前key的value值

image-20210618230605366

@Override

public V compute(A args) throws Exception {

Future future = cache.get(args);

if (future == null) {

Callable callable = new Callable() {

@Override

public V call() throws Exception {

return c.compute(args);

}

};

FutureTask futureTask = new FutureTask<>(callable);

//通过putIfAbsent()实现原子操作put

//返回的值是旧的key对应的value值

//如果存在,代表已经有现存执行这个put方法了,因此就跳过,避免计算

future = cache.putIfAbsent(args, futureTask);

if (future ==null){

future = futureTask;

System.out.println(“从FutureTask调用计算函数”);

futureTask.run();

}

}

return future.get();

}


7、计算中抛出异常—ExcecutionException

/******

@author 阿昌

@create 2021-06-19 20:54


  •  耗时计算的实现类,有概率计算失败
    

*/

public class MyFail implements Computable<String,Integer>{

@Override

public Integer compute(String arg) throws Exception {

double random = Math.random();

//模拟有概率失败

if (random>0.5){

throw new IOException(“读取文件出错了”);

}

//模拟计算

Thread.sleep(3000);

return new Integer(arg);

}

}

image-20210619205724721

image-20210619205752901

  • 手动try-catch捕获异常

image-20210619210118879

  • 针对不同的异常,做出不同的异常处理

image-20210619210151905


这出发现缓存污染问题

putIfAbsent()方法所放的值一致是同一个,所有就会一直重试

image-20210619211430166

删除缓存中的K对应的V

image-20210619211417755

public class Imooccahe7<A, V> implements Computable<A, V> {

private final ConcurrentHashMap<A, Future> cache = new ConcurrentHashMap<>();

private final Computable<A, V> c;//装饰者模式接口类

public Imooccahe7(Computable<A, V> c) {

this.c = c;

}

@Override

public V compute(A args) {

while (true){

Future future = cache.get(args);

if (future == null) {

Callable callable = new Callable() {

@Override

public V call() throws Exception {

return c.compute(args);

}

};

FutureTask futureTask = new FutureTask<>(callable);

future = cache.putIfAbsent(args, futureTask);

if (future ==null){

future = futureTask;

System.out.println(“从FutureTask调用计算函数”);

futureTask.run();

}

}

try {

return future.get();

} catch (InterruptedException e) {

cache.remove(args);

} catch (ExecutionException e) {

System.out.println(“计算错误,重新计算”);

cache.remove(args);

}catch (CancellationException e){

cache.remove(args);

System.out.println(“被取消”);

}

}

}

//主函数

public static void main(String[] args) throws Exception {

//构造函数传入我们具体进行计算的实现类

Imooccahe7<String, Integer> imooccahe7 = new Imooccahe7<>(new MyFail());

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe7.compute(“666”);

System.out.println(“第一次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe7.compute(“667”);

System.out.println(“第二次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe7.compute(“666”);

System.out.println(“第三次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

}

}

image-20210619212205274


8、缓存过期功能

//出于安全性考虑,缓存需要设置有效时间,到期自动失效

//否则如果缓存一直不失效,会出现缓存不一致的问题

public class Imooccahe8<A, V> implements Computable<A, V> {

private final ConcurrentHashMap<A, Future> cache = new ConcurrentHashMap<>();

private final Computable<A, V> c;//装饰者模式接口类

public Imooccahe8(Computable<A, V> c) {

this.c = c;

}

@Override

public V compute(A args) {

while (true) {

Future future = cache.get(args);

if (future == null) {

Callable callable = new Callable() {

@Override

public V call() throws Exception {

return c.compute(args);

}

};

FutureTask futureTask = new FutureTask<>(callable);

future = cache.putIfAbsent(args, futureTask);

if (future == null) {

future = futureTask;

System.out.println(“从FutureTask调用计算函数”);

futureTask.run();

}

}

try {

return future.get();

} catch (InterruptedException e) {

cache.remove(args);

} catch (ExecutionException e) {

System.out.println(“计算错误,重新计算”);

cache.remove(args);

} catch (CancellationException e) {

cache.remove(args);

System.out.println(“被取消”);

}

}

}

public final static ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);

//具有自动过期的计算

public V compute(A arg, long expire) {

if (expire > 0) {

pool.schedule(new Runnable() {

@Override

public void run() {

//时间到了清除缓存方法

clean(arg);

}

}, expire, TimeUnit.MILLISECONDS);

}

return compute(arg);

}

//清楚缓存方法

public synchronized void clean(A arg) {

Future future = cache.get(arg);

if (future != null) {

if (!future.isDone()) {

System.out.println(“任务被取消”);

future.cancel(true);

}

System.out.println(“过期时间到,缓存被清除”);

cache.remove(arg);

}

}

//主函数

public static void main(String[] args) throws Exception {

//构造函数传入我们具体进行计算的实现类

Imooccahe8<String, Integer> imooccahe8 = new Imooccahe8<>(new MyFail());

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe8.compute(“666”,5000L);

System.out.println(“第一次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe8.compute(“667”);

System.out.println(result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe8.compute(“666”);

System.out.println(“第二次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

Thread.sleep(6000L);

//这次计算会缓冲失效,因为主线程睡眠了6s,而一个KV的时间设置的为5s

Integer result = imooccahe8.compute(“666”);

System.out.println(“第三次计算结果:”+result);

总结

面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。

我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

面试题及解析总结

三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经

大厂面试场景

三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经

知识点总结

三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

ahe8.compute(“667”);

System.out.println(result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

try {

Integer result = imooccahe8.compute(“666”);

System.out.println(“第二次计算结果:” + result);

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

Thread.sleep(6000L);

//这次计算会缓冲失效,因为主线程睡眠了6s,而一个KV的时间设置的为5s

Integer result = imooccahe8.compute(“666”);

System.out.println(“第三次计算结果:”+result);

总结

面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。

我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

面试题及解析总结

[外链图片转存中…(img-5wQik1zQ-1714906740316)]

大厂面试场景

[外链图片转存中…(img-X9QcmPuQ-1714906740317)]

知识点总结

[外链图片转存中…(img-dG3OpGem-1714906740317)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 22
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值