精华内容
下载资源
问答
  • Java 消息队列缓存、同步(个人理解:空谈)
    2021-12-30 16:57:57

    Java 消息队列、缓存、同步、

    消息队列

    我的理解:消息队列,将消息存入消息队列,然后就OK了。

    系统之间原先调用通用接口,但引入了消息队列后,系统之间调用MQ消息队列。

    好处:响应快,能累积请求,甩手掌柜。

    // 为什么要使用MQ消息队列
    解耦复用、异步、削峰
    // 使用了MQ消息队列会带来那些隐患
    降低系统可用性、提高系统复杂度、数据一致性
    // 如何使用MQ消息队列
    // 常见的消息队列
    activeMQ、rabbitMQ、rocketMQ、kafka
    

    缓存

    我的理解:缓存,将数据备份到本地。

    系统原先调用数据库数据,但引用了缓存,系统调用缓存数据,没有调到数据,然后调用数据库数据

    好处:响应快,请求多。

    // 为什么要使用缓存
    高性能、高并发
    // 使用了缓存会带来那些隐患
    缓存与数据库双些不一致、缓存击穿、缓存穿透、缓存雪崩、缓存并发竞争
    // 如何使用缓存
    

    加锁的目的是为了同步,为了数据的一致性。

    实现同步的方式有很多:加锁,ThreadLocal当前线程变量、线程阻塞、使用线程池,

    实现加锁的方式也有很多:volatile关键字、synchronized关键字、Lock接口

    实现线程阻塞的方式也有很多:sleep() 、wait()

    分布式锁

    用在分布式系统中,每一个系统的指定进程放一个锁,同一时间,同一进程,只能有一个进程被执行。

    负载均衡

    我的理解:负载均衡,将请求合理的分配到指定的服务器。

    系统原先发送请求到xxx服务器,但引用了负载均衡,系统发送的请求到了yyy服务器。

    好处:合理分配资源

    更多相关内容
  • 缓冲队列java实现

    2021-02-12 19:46:36
    昨天在某某的提示下,终于意识到不该用阻塞队列,换成普通的List对象,这样效果就明显多啦~~又重新了一篇文档,如下提出问题:为啥要有缓冲队列?引用09年9月《程序员》上的一句话:缓冲队列就是冲着同步/互斥...

    前段时间,做了个“双缓冲队列”,可是测试的效果就是不怎么明显,理论完全都在这里,可是就是看不到效果。

    昨天在某某的提示下,终于意识到不该用阻塞队列,换成普通的List对象,这样效果就明显多啦~~

    又重新写了一篇文档,如下

    提出问题:为啥要有双缓冲队列?

    引用09年9月《程序员》上的一句话:双缓冲队列就是冲着同步/互斥的开销来的。我们知道,在多个线程并发访问同一个资源的时候,需要特别注意线程的同步问题。稍稍不注意,哦活,程序结果不正确了。最经典的就是“银行取钱”的例子,想想,都跟现金挂上钩了,看来这真不容忽视。

    今天我们要谈的不是如何去给资源加锁解锁来解决同步问题,今天的重点在于,如何将线程同步的开销降低到我们力所能及的程度。如果你觉得,你可以通过增加硬件资源来弥补程序开销,那么,你将不可能成为一个优秀的程序员。

    进入正题,先引入一个例子,两个实体:一个是玩具工厂,它的工作就是不停地生产玩具;另外一个实体就是小孩,它的工作就是不停地从工厂拿玩具。小孩不可能直接到工厂去“拿”玩具吧?呵呵,妈妈是绝对不会放心的。所以,我们有一个“搬运工”,搬运工自然要具备“存放”的功能,不然他怎么将玩具带给小孩呢,是吧。所以,我们先将搬运工定义为一个List,用来存放工厂生产出来的玩具。

    玩具类,定义一个玩具实体

    public class Toy {

    private

    String name;

    public

    String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    }

    生产玩具的玩具工厂,相当于生产者

    package twoBufferQueue;

    public class Factory extends Thread {

    public void run() {

    while (true) {

    Toy t =

    new Toy();

    t.setName("玩具");

    synchronized

    (Tools.lP) {

    if

    (Tools.lP.size() >= 2000) {

    try

    {

    Tools.lP.wait();

    }

    catch (Exception e) {

    //

    TODO: handle exception

    }

    }

    Tools.lP.add(t);

    // System.out.println("put

    one");

    }

    }

    }

    }

    小孩取玩具,相当于消费者

    package twoBufferQueue;

    public class Kid extends Thread {

    long time1 = System.currentTimeMillis();

    int count = 0;

    public void run() {

    while (true) {

    synchronized

    (Tools.lT) {

    if

    (Tools.lT.size() != 0){

    Tools.lT.remove(0);

    count++;

    }

    }

    if (count ==

    100000) {

    System.out.println("time:"

    + (System.currentTimeMillis() - time1));

    System.exit(0);

    }

    }

    }

    }

    双缓冲队列,里面有两个List

    package twoBufferQueue;

    import java.util.List;

    public class DoubleBufferList {

    private

    List lP;

    private

    List lT;

    private int

    gap;

    public

    DoubleBufferList(List lP, List lT, int gap) {

    this.lP = lP;

    this.lT = lT;

    this.gap = gap;

    }

    public

    void check() {

    Runnable runner = new Runnable() {

    public void run() {

    while (true) {

    if (lT.size() == 0) {

    synchronized (lT) {

    synchronized (lP) {

    lT.addAll(lP);

    lP.notifyAll();

    }

    lP.clear();

    展开全文
  • 在延迟队列中所保存的每一个元素内容.每当时间一到,(compareTo进行比较,getDelay()获取延迟时间),都会自动进行队里数据的弹出操作; 使用延迟队列(模拟讨论会依次离开的场景) public class Student implements ...

    在延迟队列中所保存的每一个元素内容.每当时间一到,(compareTo进行比较,getDelay()获取延迟时间),都会自动进行队里数据的弹出操作;
    使用延迟队列(模拟讨论会依次离开的场景)

    public class Student implements Delayed {
        //姓名
        private String name;
        //离开时间
        private long expire;
        //停留时间
        private long delay;
    
        public Student(String name,long delay,TimeUnit unit){
            this.name = name;
            //转换时间单位为毫秒
            this.delay = TimeUnit.MILLISECONDS.convert(delay,unit);
            //失效时间计算
            this.expire = System.currentTimeMillis() + this.delay;
        }
    
        public String toString() {
            return this.name + "同学已经达到预计的停留时间"+TimeUnit.SECONDS.convert(this.delay,TimeUnit.MILLISECONDS)+"秒,已经离开了";
        }
        /**
         * 队列弹出计算
         * @param o
         * @return
         */
        @Override
        public int compareTo(Delayed o) {
            int i = (int) (this.delay - this.getDelay(TimeUnit.MILLISECONDS));
            return i;
        }
        /**
         *延迟时间计算
         * @param
         * @return
         */
        @Override
        public long getDelay(TimeUnit unit) {
            long convert = unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
            return convert;
        }
    }
    
    public class JUCDemo {
        public static void main(String[] args) throws InterruptedException {
            //定义延迟队列
            BlockingQueue<Student> queue = new DelayQueue<>();
            //保存队列信息
            queue.put(new Student("李",3, TimeUnit.SECONDS));
            queue.put(new Student("王",5,TimeUnit.SECONDS));
    
            //判断队列是否有数据
            while (!queue.isEmpty()){
                //获取弹出数据
                Student take = queue.take();
                System.out.println(take);
                TimeUnit.SECONDS.sleep(1);
            }
        }
    }
    

    输出结果:

    李同学已经达到预计的停留时间3,已经离开了
    王同学已经达到预计的停留时间5,已经离开了
    

    使用延迟队列的主要原因是它可以实现队列的定时清理操作.那么基于这样的自动清理机制就可以实现数据缓存的操作控制.这样的操作可以极大的提升项目的并发性能;
    (在时间开发中,如果是基于数据库的查询操作,那么在多线并发量较高的情况下就有可能产生严重的性能问题,例如一个热门新闻可能会有上千万的访问量,这个时候采用直接数据库的读取模式就非常不理智.为了解决这一的问题,可以采用缓存模式,将一些重要的数据直接放到缓存里面.当不同的线程查询相同数据时先判断缓存中是否有指定内容,如果存在,则进行直接读取,如果不存在,再进行数据库加载.对于缓存中的内容还要考虑无效数据的清理问题,而有了延迟队列这种自动弹出的机制存在.这一操作实现就会变得非常容易)

    下面实现一个新闻数据的缓存操作,考虑到可能会保存有多个数据,所以讲通过Map集合实现存储,同时考虑到缓存数据的修改安全性问题,使用ConcurrentHashMap子类,另外对于数据的弹出操作将通过守护线程进行处理.

    public class News {
        private long nid;
        private String title;
        public News(long nid, String title){
            this.nid = nid;
            this.title = title;
        }
        public String toString(){
            return "新闻数据---->编号:"+this.nid+",标题:"+title;
        }
    }
    
    public class Cache<K,V> {
        //时间单位
        private static final TimeUnit TIME = TimeUnit.SECONDS;
        //缓存时间
        private static final long DELAY_SECONDS = 2;
        //缓存集合
        private Map<K,V> cacheObjects = new ConcurrentHashMap<>();
        private BlockingQueue<DelayedItem<Pair>> queue = new DelayQueue<>();
    
        //启动线程
        public Cache(){
            Thread thread = new Thread(()->{
                while (true){
                    try{
                        //数据弹出消费
                        DelayedItem<Pair> item = Cache.this.queue.take();
                        if (item != null){
                            //获取内容
                            Pair pair = item.getItem();
                            //删除数据
                            Cache.this.cacheObjects.remove(pair.key,pair.value);
                        }
                    }catch (Exception e){}
                }
            });
            thread.setDaemon(true);
            thread.start();
        }
    
        /**
         * 保存数据
         * @param key
         * @param value
         */
        public void put(K key,V value) throws InterruptedException {
            V oldValue= this.cacheObjects.put(key,value);
            //删除已有数据
            if (oldValue != null){
                this.queue.remove(oldValue);
            }
            //重新保存
            this.queue.put(new DelayedItem<Pair>(new Pair(key,value),DELAY_SECONDS,TIME));
        }
    
        /**
         * 获取缓存数据
         * @param key
         * @return
         */
        public V get(K key){
            return this.cacheObjects.get(key);
        }
    
        /**
         * 封装保存数据
         */
        private class Pair{
            private K key;
            private V value;
    
            public Pair(K key,V value){
                this.key = key;
                this.value = value;
            }
        }
    
        /**
         * 延迟数据保存
         * @param <T>
         */
        private class DelayedItem<T> implements Delayed{
            private T item;
            private long delay;
            private long expire;
    
            public DelayedItem(T item,long delay,TimeUnit unit){
                this.item = item;
                this.delay = TimeUnit.MILLISECONDS.convert(delay,unit);
                this.expire = System.currentTimeMillis() + this.delay;
            }
    
            public T getItem(){
                return this.item;
            }
    
            @Override
            public long getDelay(TimeUnit unit) {
                return unit.convert(this.expire - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
            }
    
            @Override
            public int compareTo(Delayed o) {
                return (int)(this.delay - this.getDelay(TimeUnit.MILLISECONDS));
            }
        }
    
    }
    
    public class JUCDemo2 {
        public static void main(String[] args) throws InterruptedException {
            Cache<Long,News> cache = new Cache<>();
            cache.put(1L,new News(1L,"程序员为什么秃"));
            cache.put(2L,new News(2L,"程序员为什么宅"));
            cache.put(3L,new News(3L,"程序员为什么扣"));
    
            System.out.println(cache.get(1L));
            System.out.println(cache.get(2L));
            //模拟延迟时间.2秒后清除缓存
            TimeUnit.SECONDS.sleep(3);
            System.out.println(cache.get(3L));
        }
    }
    

    输出结果:

    新闻数据---->编号:1,标题:程序员为什么秃
    新闻数据---->编号:2,标题:程序员为什么宅
    null
    

    在程序中考虑到缓存数据的自动清理问题,所以使用了延迟队列保存所以的数据信息(同时还有一份数据信息保存在Map集合中),为了保证延迟队列中的数据弹出后可以进行Map集合相应数据的删除.所以定义了一个守护线程接收延迟队列弹出的内容.由于本程序设置了默认的缓存时间为2秒,这样当2秒一过数据就会被删除.

    展开全文
  • java使用DelayQueue延迟队列和Redis缓存实现订单自动取消功能
  • Java双缓冲技术详细讲解,适合初学者,简单易懂,代码
  • Java通过缓存队列执行任务代码实现

    千次阅读 2016-02-28 16:17:09
    **Java通过缓存队列执行任务代码实现** 创建缓存队列package cn.com.job;import java.util.HashMap; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue;import cn.com.domain.User;public ...
                       **Java通过缓存队列执行任务代码实现**
    

    创建缓存队列


    package cn.com.job;

    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.LinkedBlockingQueue;

    import cn.com.domain.User;

    public class UserCacheUtil {

    private static UserCacheUtil userCacheUtil = null;
    
    private static Map<String,LinkedBlockingQueue<User>> userCacheMap = new HashMap<String,LinkedBlockingQueue<User>>();
    
    private UserCacheUtil(){}
    
    public synchronized static UserCacheUtil getInstance(){
        if(userCacheUtil==null){
            userCacheUtil = new UserCacheUtil();
        }
        return userCacheUtil;
    }
    
    public void addCache(String userId,User user){
        LinkedBlockingQueue<User> linkList = userCacheMap.get(userId);
        if(linkList==null){
            linkList = new LinkedBlockingQueue<User>();
            linkList.offer(user);
            userCacheMap.put(userId, linkList);
            System.out.println(userId+"加入队列---------------------");
            TreadPoolUtis.getInstance().execute(userId);
        }else{
            linkList.offer(user);
        }
    }
    
    public User getNextElement(String userId){
        LinkedBlockingQueue<User> linkList = userCacheMap.get(userId);
        User user = null;
        if(linkList!=null){
            user = linkList.poll();
        }
        if(user==null){
            System.out.println("清空缓存队列");
            userCacheMap.put(userId, null);
        }
        return user;
    }
    

    }


    创建线程池


    package cn.com.job;

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    import cn.com.domain.User;

    public class TreadPoolUtis{

    private static TreadPoolUtis treadPoolUtis = null;
    
    private ExecutorService executer;
    
    private final static int MAX=10;
    
    private TreadPoolUtis(){
        executer = Executors.newFixedThreadPool(MAX);
    }
    
    public synchronized static TreadPoolUtis getInstance(){
        if(treadPoolUtis == null){
            treadPoolUtis = new TreadPoolUtis();
        }
        return treadPoolUtis;
    }
    
    public void execute(final String userId){
        executer.execute(new Runnable() {
            @Override
            public void run() {
                User user = UserCacheUtil.getInstance().getNextElement(userId);
                while(user!=null){
                    for(int i=0;i<1;i++){
                        System.out.println(user.getUserName()+"执行!"+i);
                    }
                    user = UserCacheUtil.getInstance().getNextElement(userId);
                }
            }
        });
    }
    

    }


    测试类


    package cn.com.test;

    import cn.com.domain.User;
    import cn.com.job.UserCacheUtil;

    public class TestUserCache {

    public static void main(String[] args) {
    
        User user = new User();
        user.setUserName("潘博");
        user.setUserId(1001);
        user.setAddress("河南省鹿邑县!!!");
    
        UserCacheUtil.getInstance().addCache("1001", user);
        UserCacheUtil.getInstance().addCache("1001", user);
    
        /*User user2 = new User();
        user2.setUserName("潘博2");
        user2.setUserId(1002);
        user2.setAddress("河南省鹿邑县2222!!!");
        User user3 = new User();
        user3.setUserName("潘博3");
        user3.setUserId(1003);
        user3.setAddress("河南省鹿邑县3333!!!");
    
        User user4 = new User();
        user4.setUserName("潘博4");
        user4.setUserId(1004);
        user4.setAddress("河南省鹿邑县4444!!!");
    
        UserCacheUtil.getInstance().addCache("1002", user2);
    
        UserCacheUtil.getInstance().addCache("1003", user3);
        UserCacheUtil.getInstance().addCache("1004", user4);*/
    }
    

    }

    已测试。

    展开全文
  • Java双缓冲队列实现

    千次阅读 2017-04-18 09:30:15
    Java实现了一个缓冲队列,并给出了实例代码
  • NULL 博文链接:https://128kj.iteye.com/blog/1665616
  • 今天天朗气清,吃饱撑之余,回想了想之前面试阿里巴巴的时候,面试官问的缓存和数据库,两者在生产环境中,容易出现数据不一致的情况,这对业务是十分影响的,我当时回答得很不错,面试官还是排板叫你滚的那种,哈哈...
  • 高并发下如何保证数据库和缓存双写一致性?

    千次阅读 热门讨论 2022-04-01 21:18:04
    数据库和缓存(比如:redis)双写数据一致性问题,是一个跟开发语言无关的公共问题。尤其在高并发的场景下,这个问题变得更加严重。 我很负责的告诉你,该问题无论在面试,还是工作中遇到的概率非常大,所以非常有...
  • 服务器端缓冲队列s/c,简单的实现了服务器端的队列实现
  • 缓存 队列 kettle

    2018-06-03 09:26:01
    缓存 队列 kettle 缓存 队列 kettle 缓存 队列 kettle 缓存 队列 kettle
  • 分布式之数据库和缓存双写一致性方案解析 1. 先更新数据库,再更新缓存 不可行。 原因分析: 频繁更新缓存浪费资源(多读少的场景) 缓存数据计算复杂,浪费性能(可能涉及多张表的计算) 线程并发安全问题。...
  • redis 延时队列

    2018-08-10 17:13:11
    将整个Redis当做消息池,以kv形式存储消息 使用ZSET做优先队列,按照score维持优先级
  • java实现带过期时间的缓存

    千次阅读 2021-02-28 16:19:07
    /** * 让过期时间最小的数据排在队列前,在清除过期数据时 * ,只需查看缓存最近的过期数据,而不用扫描全部缓存 * * @see Node#compareTo(Node) * @see SwapExpiredNodeWork#run() */ private PriorityQueue ...
  • Java面试题消息队列

    千次阅读 2022-03-27 17:44:09
    消息队列的架构图: 生产者发送消息的流程: -- 消息的发送者(Producer)和RabbitMQ建立连接,获取通道. -- 生产者发送消息到指定虚拟机中的交换机(exchange), -- 交换机通过routhingKey来获取对应的队列. 消费者...
  • Java队列、线程池及ThreadPoolExecutor自定义线程池实现
  • 本博文参考网上相关的博文,详细的整理下缓存数据库数据一致性的问题,并且给出基于Java的代码解决方案 关于缓存数据库数据一致性的解决方案,网上有很多,但是大都是偏向理论的,且大多数使用分布式锁来实现的,...
  • [提前声明] 文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的...本次主要给各位分享Redis与SpringBoot的集成使用,缓存案例,消息队列案例,广播案例 初识Redis Redis是开源的(BSD许可)内...
  • JAVA循环队列

    千次阅读 2017-09-15 15:25:44
    一、JAVA 中已经自带了 Queue、DQueue、ArrayList、LinkedList 等常用的数据结构,为什么还要单独实现循环队列? 之所以使用自定义循环队列,出发点还是基于我们在实际应用中对于数据处理各种各样的需求。使用...
  • 线程池的三种缓存队列

    千次阅读 2018-08-14 16:31:48
    最近在看java的线程池,对于里面的三种缓存队列里面进行对比学习了下,感觉自己测试下来的结果和网上有些知识点不同相同,所以还希望有人能帮我解惑下。 概述 队列 简单解释 SynchrousQueue 不会保存提交...
  • 数据缓存Java实现

    千次阅读 2019-02-15 17:13:04
     对于缓存大家应该都不陌生,缓存的核心是用空间换实践,通过分配一块高速存储区域(一般都是内存)来提高数据的读写效率,其实现的难点在于清空策略的实现,比较合理的思路就是定时回收与及时判断数据是否过期相...
  • 介绍了memcached缓存开源框架在windows下的安装,以及如何用java访问缓存server,并结合原理和代码讲解。代码测过可用。
  • 展开全部Java中可以使用队列来保存62616964757a686964616fe59b9ee7ad9431333337613163数据,当使用的时候,加上锁,防止其他进程访问,当不用的时候保存到数据库里面,示例如下:packagecom.henry;importjava.util....
  • Java 常用缓存淘汰算法解析

    万次阅读 2021-08-14 09:50:21
    对于很多缓存中间件来说,内存是其操作的主战场,以redis来说,redis是很多互联网公司必备的选择,redis具有高效、简洁且易用的诸多特性被大家广泛使用,但我们知道,redis操作大多数属于内存性级操作,如果用于存放...
  • 1.java实现延迟消息(队列DelayQueue) DelayQueue是一个支持延时获取元素的无界阻塞队列队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。...
  • MySQL数据库与Redis缓存双写一致性

    千次阅读 多人点赞 2022-04-02 13:57:42
    MySQL数据库与Redis缓存双...延时删删除缓存重试机制异步优化方式:消息队列异步优化方式:基于订阅binlog的同步机制小结 问题 你只要用缓存,就可能会涉及到缓存与数据库存储双写,你只要是双写,就一定会有数据一
  • 一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求“缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和请求串行化,串到一个内存队列里...
  • Java中几种高性能的队列

    千次阅读 2020-06-14 23:45:56
    一、阻塞队列 由于阻塞队列(BlockingQueue)是加了锁的,所以在阻塞队列是一个性能瓶颈,影响中间件传输数据速度。 二、disruptor Disruptor是一个无锁高性能安全的队列 三、JCTools 最后采用了一种github上...
  • JAVA多线程与队列

    千次阅读 2018-07-07 10:14:20
    JAVA 已经给我们提供了比较好的队列实现Queue,继承于Collection。 本次我使用的是BlockingQueue,继承于Queue。 在

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 191,325
精华内容 76,530
关键字:

缓存双写java队列

java 订阅