মেয়াদ উত্তীর্ণ কীগুলির সাথে জাভা সময়-ভিত্তিক মানচিত্র / ক্যাশে [বন্ধ]


253

আপনারা কি এমন কোনও জাভা মানচিত্র বা অনুরূপ স্ট্যান্ডার্ড ডেটা স্টোর সম্পর্কে জানেন যা প্রদত্ত সময়সীমার পরে স্বয়ংক্রিয়ভাবে এন্ট্রিগুলি পরিষ্কার করে? এর অর্থ বার্ধক্য, যেখানে পুরানো মেয়াদোত্তীর্ণ প্রবেশদ্বারগুলি স্বয়ংক্রিয়ভাবে "বয়সের বাইরে" প্রবেশ করে।

সাধারণত ওপেন সোর্স লাইব্রেরিতে মাভেনের মাধ্যমে অ্যাক্সেসযোগ্য?

আমি নিজে কার্যকারিতা বাস্তবায়নের উপায়গুলি জানি এবং অতীতেও এটি বেশ কয়েকবার করেছি, সুতরাং আমি সেই বিষয়ে পরামর্শের জন্য বলছি না, তবে একটি ভাল রেফারেন্স বাস্তবায়নের নির্দেশকগুলির জন্য।

WeakReference মত ভিত্তিক সমাধান WeakHashMap একটি বিকল্প, কারণ আমার চাবি সম্ভাবনা বেশি অ অন্তরীণ স্ট্রিং হতে হয় না এবং আমি একটি কনফিগার সময়সীমার যে আবর্জনা সংগ্রাহক উপর নির্ভরশীল নয় চাই।

এহচে ক্যাচ এমন একটি বিকল্প যা আমি নির্ভর করতে চাই না কারণ এটির জন্য বাহ্যিক কনফিগারেশন ফাইলগুলি দরকার। আমি একটি কোড-কেবল সমাধান খুঁজছি।


1
গুগল সংগ্রহগুলি (এখন পেয়ারা বলা হয়) দেখুন। এটিতে একটি মানচিত্র রয়েছে যা এন্ট্রিগুলি স্বয়ংক্রিয়ভাবে শেষ করতে পারে।
dty

3
253 টি আপভোট এবং 176 কে মতামত - যা এই বিষয়টির জন্য অনুসন্ধান ইঞ্জিনগুলিতে অত্যন্ত উচ্চতর - একটি প্রশ্নটি কীভাবে বেআইনিভাবে নির্দেশিকাটি মেটেনি তাই বন্ধ করা হয়েছে
ব্রায়ান

উত্তর:


320

হ্যাঁ. গুগল সংগ্রহ বা পেয়ারার নাম হিসাবে এটি এখন ম্যাপমেকার নামে কিছু রয়েছে যা ঠিক তা করতে পারে।

ConcurrentMap<Key, Graph> graphs = new MapMaker()
   .concurrencyLevel(4)
   .softKeys()
   .weakValues()
   .maximumSize(10000)
   .expiration(10, TimeUnit.MINUTES)
   .makeComputingMap(
       new Function<Key, Graph>() {
         public Graph apply(Key key) {
           return createExpensiveGraph(key);
         }
       });

হালনাগাদ:

পেয়ারা ১০.০ (২৮ শে সেপ্টেম্বর, ২০১১ প্রকাশিত) হিসাবে এই ম্যাপমেকার পদ্ধতির অনেকগুলিই নতুন ক্যাশেবিল্ডারের পক্ষে অবচিত করা হয়েছে :

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize(10000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build(
        new CacheLoader<Key, Graph>() {
          public Graph load(Key key) throws AnyException {
            return createExpensiveGraph(key);
          }
        });

5
আশ্চর্যজনক, আমি জানতাম পেয়াদের একটি উত্তর আছে তবে আমি এটি খুঁজে পেলাম না! (+1)
শান প্যাট্রিক ফ্লয়েড

12
ভি 10 হিসাবে, আপনার পরিবর্তে ক্যাচবিল্ডার ব্যবহার করা উচিত ( guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/… ) যেহেতু মেয়াদোত্তীর্ণকরণ ইত্যাদি ম্যাপমেকারে
অবহিত

49
সতর্কতা ! ব্যবহার করা weakKeys()ইঙ্গিত দেয় যে কী == শব্দার্থবিদ্যা ব্যবহার করে, না তুলনা করা হয় equals()। আমার স্ট্রিং-কীড ক্যাশেটি কেন কাজ করছে না তা ভেবে 30 মিনিট হারিয়েছি :)
লরেন্ট গ্রোগোয়ার

3
ভাবেন, @ লরেন্ট যে জিনিসটির বিষয়ে উল্লেখ করেছেন weakKeys()তা গুরুত্বপূর্ণ। weakKeys()90% সময় প্রয়োজন হয় না।
মনু মঞ্জুনাথ

3
@ শেরভিন অ্যাসগারি নতুনদের জন্য (নিজেকে অন্তর্ভুক্ত করা হয়েছে) আপনি কি নিজের আপডেট হওয়া পেয়ারা উদাহরণটিকে এমন কোনওটিতে পরিবর্তন করতে পারেন যা লোডিং ক্যাশের পরিবর্তে ক্যাশে ব্যবহার করে? এটি প্রশ্নের সাথে আরও ভাল মিলবে (যেহেতু লোডিংক্যাচে এমন বৈশিষ্ট্য রয়েছে যা মেয়াদোত্তীর্ণ এন্ট্রি সহ মানচিত্রকে অতিক্রম করে এবং এটি তৈরি করা আরও জটিল) গিথুব.com
google/

29

এটি একই নমুনা বাস্তবায়ন যা আমি একই প্রয়োজনীয়তার জন্য করেছি এবং সম্মতিটি ভালভাবে কাজ করে। কারও পক্ষে উপকারী হতে পারে।

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 
 * @author Vivekananthan M
 *
 * @param <K>
 * @param <V>
 */
public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {

    private static final long serialVersionUID = 1L;

    private Map<K, Long> timeMap = new ConcurrentHashMap<K, Long>();
    private long expiryInMillis = 1000;
    private static final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss:SSS");

    public WeakConcurrentHashMap() {
        initialize();
    }

    public WeakConcurrentHashMap(long expiryInMillis) {
        this.expiryInMillis = expiryInMillis;
        initialize();
    }

    void initialize() {
        new CleanerThread().start();
    }

    @Override
    public V put(K key, V value) {
        Date date = new Date();
        timeMap.put(key, date.getTime());
        System.out.println("Inserting : " + sdf.format(date) + " : " + key + " : " + value);
        V returnVal = super.put(key, value);
        return returnVal;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        for (K key : m.keySet()) {
            put(key, m.get(key));
        }
    }

    @Override
    public V putIfAbsent(K key, V value) {
        if (!containsKey(key))
            return put(key, value);
        else
            return get(key);
    }

    class CleanerThread extends Thread {
        @Override
        public void run() {
            System.out.println("Initiating Cleaner Thread..");
            while (true) {
                cleanMap();
                try {
                    Thread.sleep(expiryInMillis / 2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void cleanMap() {
            long currentTime = new Date().getTime();
            for (K key : timeMap.keySet()) {
                if (currentTime > (timeMap.get(key) + expiryInMillis)) {
                    V value = remove(key);
                    timeMap.remove(key);
                    System.out.println("Removing : " + sdf.format(new Date()) + " : " + key + " : " + value);
                }
            }
        }
    }
}


গিট রেপো লিঙ্ক (শ্রোতার প্রয়োগের সাথে)

https://github.com/vivekjustthink/WeakConcurrentHashMap

চিয়ার্স !!


কেন আপনি cleanMap()কাফের অর্ধেক সময় নির্বাহ করবেন?
এলিউক্স

Bcoz এটি নিশ্চিত করে যে কীগুলি মেয়াদোত্তীর্ণ হয়ে গেছে (সরানো) এবং চূড়ান্ত লুপিং থেকে থ্রেড এড়িয়ে চলে।
বিবেক

@ ভিভেক তবে এই প্রয়োগের সাথে সর্বাধিক (এক্সপায়ারইনমিলিস / ২) এন্ট্রিগুলি থাকতে পারে যা ইতিমধ্যে মেয়াদোত্তীর্ণ হয়ে গেছে তবে ক্যাশে উপস্থিত রয়েছে। থ্রেড মেয়াদোত্তীর্ণ হওয়ার পরে এন্ট্রিগুলি মুছে ফেললেমিলিস / 2 পিরিয়ড
ishষি 7007 বনসোদ

19

আপনি আমার স্ব-মেয়াদোত্তীর্ণ হ্যাশ মানচিত্রটি প্রয়োগের চেষ্টা করতে পারেন । মেয়াদোত্তীর্ণ এন্ট্রিগুলি অপসারণ করতে এই প্রয়োগটি থ্রেড ব্যবহার করে না, পরিবর্তে এটি DelayQueue ব্যবহার করে যা প্রতিটি ক্রিয়াকলাপে স্বয়ংক্রিয়ভাবে পরিষ্কার হয়।


আমি পেয়ারা সংস্করণটি আরও ভাল পছন্দ করি তবে ছবিতে সম্পূর্ণতা যুক্ত করার জন্য +1
সান প্যাট্রিক ফ্লয়েড

@ পিয়ারো 86৮ আমি পদ্ধতিতে মেয়াদোত্তীর্ণে (এক্সপায়ারিংকি <কে> বিলম্বকী) দেরিতে কিউইউ.পল () -কে কল করব। আপনি একটি নির্বিচারে এক্সপায়ারিংকে শিথিল করতে পারেন যা পরে ক্লিনআপ () - এ একটি ফুটো কাজে লাগানো যায় না।
স্টিফান জোবেল

1
আরেকটি সমস্যা: আপনি বিভিন্ন লাইফটাইমের সাথে একই কীটি দু'বার রাখতে পারবেন না। ক) পুটের পরে (1, 1, শর্টলাইভেড), তারপর খ) পুট (1, 2, লংলাইভড) কী 1 এর মানচিত্রের এন্ট্রি শর্টলাইভড এমএসের পরে চলে যাবে যতক্ষণ না লম্বা লাইভডই হোক না কেন।
স্টিফান জোবেল

আপনার মতামতে জন্য ধন্যবাদ। দয়া করে এই সমস্যাগুলি মন্তব্য হিসাবে মন্তব্য করতে পারেন?
প্যাকান

আপনার পরামর্শ অনুযায়ী স্থির। ধন্যবাদ।
প্যাকান

19

এ্যাপাচি মেয়াদ শেষ হওয়ার জন্য অ্যাপাচি কমন্সে মানচিত্রের সজ্জা রয়েছে: প্যাসিভএক্সপায়ারিং ম্যাপ এটি পেয়ারা থেকে ক্যাশের চেয়ে আরও সহজ।

পিএস সাবধান হন, এটি সিঙ্ক্রোনাইজ করা হয়নি।


1
এটি সহজ, তবে আপনি কোনও এন্ট্রি অ্যাক্সেস করার পরে এটি মেয়াদোত্তীকরণের সময়টি পরীক্ষা করে।
Badie

হিসাবে প্রতি Javadoc : যখন পদ্ধতি পুরো মানচিত্রটি বিষয়বস্তু অ্যাক্সেস জড়িত invoking (অর্থাত containsKey (অবজেক্ট), entrySet () ইত্যাদি) এই প্রসাধক সব মেয়াদ শেষ হওয়া এন্ট্রি অপসারণ করে পূর্বে আসলে আবাহন সমাপ্তির জন্য।
এনএস ডু টোইট

আপনি যদি এই লাইব্রেরির সর্বশেষ সংস্করণটি দেখতে চান (অ্যাপাচি কমন্স কমন্স-কালেকশন 4) এখানে mvnrepository
NS du Toit

3

আপনি যা চান তার জন্য ehcache এর মতো শব্দগুলি ওভারকিল হয় তবে নোট করুন যে এটির জন্য বাহ্যিক কনফিগারেশন ফাইলের দরকার নেই।

কনফিগারেশনটিকে ঘোষিত কনফিগারেশন ফাইলগুলিতে সরানো সাধারণত একটি ভাল ধারণা (যাতে কোনও নতুন ইনস্টলেশনের জন্য আলাদা সমাপ্তির সময় প্রয়োজন হয় তখন আপনাকে পুনরায় সংকলনের প্রয়োজন হয় না) তবে এটি কোনও প্রয়োজন হয় না, আপনি এখনও প্রোগ্রামিয়ালি কনফিগার করতে পারেন। http://www.ehcache.org/documentation/user-guide/configuration


2

গুগল সংগ্রহগুলিতে (পেয়ারা) ম্যাপমেকার রয়েছে যাতে আপনি সময়সীমা নির্ধারণ করতে পারেন (মেয়াদোত্তীকরণের জন্য) এবং আপনি নিজের পছন্দসই উদাহরণগুলি তৈরি করতে কোনও কারখানা পদ্ধতি ব্যবহার করে বেছে বেছে নরম বা দুর্বল রেফারেন্স ব্যবহার করতে পারেন।


2

আপনি অ্যাপাচি মিনা প্রকল্পের একটি ক্লাস http://www.java2s.com/ কোড / জাভা / সংগ্রহগুলি- ডেটা-স্ট্রাকচার / এক্সপায়ারিং ম্যাপ.htm মেয়াদ শেষ হওয়ার চেষ্টা করতে পারেন


2

কারও যদি একটি সাধারণ জিনিস প্রয়োজন হয়, নিম্নলিখিতটি একটি সাধারণ কী-সমাপ্তির সেট। এটি সহজেই কোনও মানচিত্রে রূপান্তরিত হতে পারে।

public class CacheSet<K> {
    public static final int TIME_OUT = 86400 * 1000;

    LinkedHashMap<K, Hit> linkedHashMap = new LinkedHashMap<K, Hit>() {
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, Hit> eldest) {
            final long time = System.currentTimeMillis();
            if( time - eldest.getValue().time > TIME_OUT) {
                Iterator<Hit> i = values().iterator();

                i.next();
                do {
                    i.remove();
                } while( i.hasNext() && time - i.next().time > TIME_OUT );
            }
            return false;
        }
    };


    public boolean putIfNotExists(K key) {
        Hit value = linkedHashMap.get(key);
        if( value != null ) {
            return false;
        }

        linkedHashMap.put(key, new Hit());
        return true;
    }

    private static class Hit {
        final long time;


        Hit() {
            this.time = System.currentTimeMillis();
        }
    }
}

2
এটি একক থ্রেড পরিস্থিতির জন্য ঠিক আছে, তবে এটি একযোগে পরিস্থিতিতে মারাত্মকভাবে ভেঙে যাবে।
সান প্যাট্রিক ফ্লয়েড

@ সানপ্যাট্রিকফ্লয়ড আপনার মানে লিংকডহ্যাশম্যাপের মতো ?! লিঙ্কডহ্যাশম্যাপ, হ্যাশম্যাপের মতো "এটি অবশ্যই বাহ্যিকভাবে সিঙ্ক্রোনাইজ করতে হবে" আপনি নাম দিন।
palindrom

হ্যাঁ, এই সকলের মতো, তবে পেয়ারা ক্যাশের মতো নয় (স্বীকৃত উত্তর)
সান প্যাট্রিক ফ্লয়েড

এছাড়াও, System.nanoTime()সিস্টেমের বিভিন্ন সময়ের উপর নির্ভর করে যেমন সিস্টেমের সময় নির্ভর করে তত্ক্ষণাতীত না হয়ে থাকতে পারে বলে সিস্টেমকন্টারটাইমমিলিস () সামঞ্জস্যপূর্ণ নয়।
এরকসেন

2

সাধারণত, একটি ক্যাশে কিছু সময় অবজেক্টগুলি রাখা উচিত এবং কিছু সময় পরে সেগুলি প্রকাশ করে। কোন অবজেক্ট ধরে রাখার জন্য ভাল সময়টি নির্ভর করে ব্যবহারের ক্ষেত্রে। আমি চেয়েছিলাম এই জিনিসটি সহজ হোক, কোনও থ্রেড বা সময়সূচি না রয়েছে। এই পদ্ধতির আমার জন্য কাজ করে। এর বিপরীতে SoftReference, অবজেক্টগুলি কিছুটা ন্যূনতম সময়ের জন্য উপলব্ধ থাকার গ্যারান্টিযুক্ত। তবে, যতক্ষণ না সূর্য একটি লাল দৈত্য রূপান্তরিত হয় ততক্ষণ স্মৃতিতে থাকবেন না

ব্যবহারের উদাহরণ হিসাবে একটি ধীরে ধীরে প্রতিক্রিয়াশীল সিস্টেমের কথা চিন্তা করুন যা একটি অনুরোধ সম্প্রতি করা হয়েছে কিনা তা পরীক্ষা করতে সক্ষম হবে এবং সেই ক্ষেত্রে দু'বার অনুরোধ করা পদক্ষেপটি না করা, এমনকি যদি কোনও ব্যস্ত ব্যবহারকারী কয়েকবার বোতামটি হিট করেও। তবে, কিছুক্ষণ পরে যদি একই ক্রিয়াটির জন্য অনুরোধ করা হয়, তবে এটি আবার সম্পাদিত হবে।

class Cache<T> {
    long avg, count, created, max, min;
    Map<T, Long> map = new HashMap<T, Long>();

    /**
     * @param min   minimal time [ns] to hold an object
     * @param max   maximal time [ns] to hold an object
     */
    Cache(long min, long max) {
        created = System.nanoTime();
        this.min = min;
        this.max = max;
        avg = (min + max) / 2;
    }

    boolean add(T e) {
        boolean result = map.put(e, Long.valueOf(System.nanoTime())) != null;
        onAccess();
        return result;
    }

    boolean contains(Object o) {
        boolean result = map.containsKey(o);
        onAccess();
        return result;
    }

    private void onAccess() {
        count++;
        long now = System.nanoTime();
        for (Iterator<Entry<T, Long>> it = map.entrySet().iterator(); it.hasNext();) {
            long t = it.next().getValue();
            if (now > t + min && (now > t + max || now + (now - created) / count > t + avg)) {
                it.remove();
            }
        }
    }
}

সুন্দর, আপনাকে ধন্যবাদ
বিগবাডমাউস

1
হ্যাশম্যাপ থ্রেড নিরাপদ নয়, রেস শর্তের কারণে, মানচিত্র.পুট ক্রিয়াকলাপ বা মানচিত্রের আকার পরিবর্তন করার ফলে ডেটা দুর্নীতি হতে পারে। এখানে দেখুন: mailinator.blogspot.com/2009/06/be
beauty-race-condition.html

সেটা সত্য. প্রকৃতপক্ষে, বেশিরভাগ জাভা ক্লাস থ্রেড নিরাপদ নয়। আপনার যদি থ্রেড সুরক্ষার প্রয়োজন হয় তবে আপনার নকশার প্রতিটি ক্ষতিগ্রস্থ শ্রেণীর এটি প্রয়োজনীয়তা পূরণ করে কিনা তা পরীক্ষা করে দেখতে হবে।
ম্যাথিয়াস রাঞ্জে

1

পেয়ারা ক্যাশে বাস্তবায়ন করা সহজ gu আমরা পেয়ারা ক্যাশে ব্যবহার করে সময় ভিত্তিতে কী শেষ করতে পারি। আমি পুরোপুরি পোস্ট পড়েছি এবং নীচে আমার অধ্যয়নের কী দেয়।

cache = CacheBuilder.newBuilder().refreshAfterWrite(2,TimeUnit.SECONDS).
              build(new CacheLoader<String, String>(){
                @Override
                public String load(String arg0) throws Exception {
                    // TODO Auto-generated method stub
                    return addcache(arg0);
                }

              }

তথ্যসূত্র: পেয়ারা ক্যাশে উদাহরণ


1
এখনই কাজ করছে না বলে লিঙ্কটি আপডেট করুন
স্মাইয়কভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.