"জাভা ডেটফর্ম্যাট থ্রেডসেফ নয়" এর ফলে কী ঘটে?


143

সবাই জাভা ডেটফর্ম্যাট থ্রেড নিরাপদ না হওয়ার বিষয়ে সতর্ক করে এবং আমি ধারণাটি তাত্ত্বিকভাবে বুঝতে পারি।

তবে এর কারণে আমরা কোন আসল সমস্যাগুলির মুখোমুখি হতে পারি তা কল্পনা করতে পারছি না। বলুন, আমার একটি ক্লাসে একটি ডেটফর্ম্যাট ক্ষেত্র এবং এটি বহু শ্রেণীর পরিবেশে ক্লাসে বিভিন্ন পদ্ধতিতে (ফর্ম্যাট করার তারিখ) ব্যবহৃত হয়।

এই কারণ হবে:

  • বিন্যাস ব্যতিক্রমের মতো কোনও ব্যতিক্রম
  • ডেটা মধ্যে তাত্পর্য
  • অন্য কোন ইস্যু?

এছাড়াও, দয়া করে কেন তা ব্যাখ্যা করুন।


1
এটিই এর দিকে পরিচালিত করে: stackoverflow.com/questions/14309607/…
কাঁচ

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

উত্তর:


262

এর চেষ্টা করে দেখুন।

এখানে এমন একটি প্রোগ্রাম রয়েছে যাতে একাধিক থ্রেড ভাগ করে নেওয়া ব্যবহার করে SimpleDateFormat

প্রোগ্রাম :

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

    final DateFormat format = new SimpleDateFormat("yyyyMMdd");

    Callable<Date> task = new Callable<Date>(){
        public Date call() throws Exception {
            return format.parse("20101022");
        }
    };

    //pool with 5 threads
    ExecutorService exec = Executors.newFixedThreadPool(5);
    List<Future<Date>> results = new ArrayList<Future<Date>>();

    //perform 10 date conversions
    for(int i = 0 ; i < 10 ; i++){
        results.add(exec.submit(task));
    }
    exec.shutdown();

    //look at the results
    for(Future<Date> result : results){
        System.out.println(result.get());
    }
}

এটি কয়েকবার চালান এবং আপনি দেখতে পাবেন:

ব্যতিক্রম :

এখানে কিছু উদাহরণ আছে:

1।

Caused by: java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Long.parseLong(Long.java:431)
    at java.lang.Long.parseLong(Long.java:468)
    at java.text.DigitList.getLong(DigitList.java:177)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1298)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)

2।

Caused by: java.lang.NumberFormatException: For input string: ".10201E.102014E4"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1224)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1303)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1589)

3।

Caused by: java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1084)
    at java.lang.Double.parseDouble(Double.java:510)
    at java.text.DigitList.getDouble(DigitList.java:151)
    at java.text.DecimalFormat.parse(DecimalFormat.java:1303)
    at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1936)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1312)

ভুল ফলাফল :

Sat Oct 22 00:00:00 BST 2011
Thu Jan 22 00:00:00 GMT 1970
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Thu Oct 22 00:00:00 GMT 1970
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010

সঠিক ফলাফল :

Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010
Fri Oct 22 00:00:00 BST 2010

মাল্টি-থ্রেড এনভায়রনমেন্টে ডেটফরম্যাটগুলি নিরাপদে ব্যবহারের জন্য অন্য পদ্ধতি হ'ল অবজেক্টটি ThreadLocalধরে রাখতে ভেরিয়েবল ব্যবহার করা DateFormat, যার অর্থ প্রতিটি থ্রেডের নিজস্ব অনুলিপি থাকবে এবং এটি প্রকাশের জন্য অন্যান্য থ্রেডের জন্য অপেক্ষা করার প্রয়োজন নেই। এই হল কিভাবে:

public class DateFormatTest {

  private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
    @Override
    protected DateFormat initialValue() {
        return new SimpleDateFormat("yyyyMMdd");
    }
  };

  public Date convert(String source) throws ParseException{
    Date d = df.get().parse(source);
    return d;
  }
}

আরও বিশদ সহ এখানে একটি ভাল পোস্ট


1
আমি এই উত্তরটি ভালবাসি :-)
সুন্দররাজ গোবিন্দসামি

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

30

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

এটি কীভাবে ঘটতে পারে তা কল্পনা করা সহজ: পার্সিংয়ের ক্ষেত্রে প্রায়শই আপনি এতক্ষণ যা পড়েছেন তা নির্দিষ্ট পরিমাণের রাজ্য বজায় রাখা জড়িত। যদি দুটি থ্রেড উভয় একই স্থানে পদদলিত হয় তবে আপনার সমস্যা হবে। উদাহরণস্বরূপ, প্রকারের ক্ষেত্রটি DateFormatউন্মুক্ত করে এবং কোডটির কোডটি দেখে কিছু পদ্ধতি কল করে এবং অন্যরা কল করে । এটি পরিষ্কারভাবে থ্রেড-নিরাপদ নয়।calendarCalendarSimpleDateFormatcalendar.set(...)calendar.get(...)

আমি মধ্যে লাগছিল নি সঠিক কেন বিবরণ DateFormatথ্রেড-নিরাপদ না হয়, কিন্তু আমার জন্য এটা জানা এটা যথেষ্ট নয় সিঙ্ক্রোনাইজেশন ছাড়া অনিরাপদ - অ নিরাপত্তা সঠিক বিনয় এমনকি রিলিজ মধ্যে পরিবর্তন হতে পারে।

ব্যক্তিগতভাবে আমি থেকে পারজার ব্যবহার করেন Joda সময় পরিবর্তে, তারা হয় থ্রেড নিরাপদ - এবং Joda সময় দিয়ে শুরু করতে অনেক ভালো তারিখ এবং সময় এপিআই :)


1
এর ব্যবহার প্রয়োগ করতে +1 জোডাটাইম এবং সোনার: mestachs.wordpress.com/2012/03/17/…
mestachs

18

আপনি যদি জাভা 8 ব্যবহার করেন তবে আপনি ব্যবহার করতে পারেন DateTimeFormatter

কোনও প্যাটার্ন থেকে তৈরি একটি ফর্ম্যাটার প্রয়োজনীয় হিসাবে যতবার ব্যবহার করা যেতে পারে, এটি পরিবর্তনযোগ্য এবং থ্রেড-নিরাপদ।

কোড:

LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String text = date.format(formatter);
System.out.println(text);

আউটপুট:

2017-04-17

10

মোটামুটি, আপনি DateFormatঅনেক থ্রেড দ্বারা অ্যাক্সেস করা একটি বস্তুর উদাহরণ পরিবর্তনশীল হিসাবে সংজ্ঞায়িত করা উচিত নয় , বা static

তারিখের ফর্ম্যাটগুলি সিঙ্ক্রোনাইজ করা হয় না। প্রতিটি থ্রেডের জন্য পৃথক ফর্ম্যাট উদাহরণ তৈরি করার পরামর্শ দেওয়া হয়।

সুতরাং, যদি আপনার Foo.handleBar(..)একাধিক থ্রেড দ্বারা অ্যাক্সেস করা হয় তবে পরিবর্তে:

public class Foo {
    private DateFormat df = new SimpleDateFormat("dd/mm/yyyy");

    public void handleBar(Bar bar) {
        bar.setFormattedDate(df.format(bar.getStringDate());  
    }
}

আপনার ব্যবহার করা উচিত:

public class Foo {

    public void handleBar(Bar bar) {
        DateFormat df = new SimpleDateFormat("dd/mm/yyyy");
        bar.setFormattedDate(df.format(bar.getStringDate());  
    }
}

এছাড়াও, সব ক্ষেত্রে, একটি না static DateFormat

জন স্কিটির দ্বারা উল্লিখিত হিসাবে, আপনি বাহ্যিক সিঙ্ক্রোনাইজেশন সম্পাদনের ক্ষেত্রে স্থিতিশীল এবং একটি ভাগ করে নেওয়া উদাহরণ ভেরিয়েবল উভয়ই থাকতে পারে (যেমন synchronizedকলগুলিতে প্রায় ব্যবহার করুন DateFormat)


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

1
থেকে পুরোপুরি অন্য ভালো - যদিও এটি আপনি একটি স্ট্যাটিক DateFormat আছে নেওয়াটা ঠিক হবে করেনি সুসংগত করুন। এটি SimpleDateFormatখুব ঘন ঘন একটি নতুন তৈরির চেয়ে অনেক ক্ষেত্রে ভাল পারফরম্যান্স করতে পারে । এটি ব্যবহারের প্যাটার্নের উপর নির্ভর করবে।
জন স্কিটি

1
আপনি কী দয়া করে ব্যাখ্যা করতে পারেন যে স্থির দৃষ্টিকোণটি কীভাবে বহু-থ্রেড পরিবেশে সমস্যা সৃষ্টি করতে পারে?
আলেকজান্দ্র

4
কারণ এটি উদাহরণের ভেরিয়েবলগুলিতে মধ্যবর্তী গণনাগুলি সঞ্চয় করে এবং এটি থ্রেড-নিরাপদ নয়
বোঝো

2

তারিখের ফর্ম্যাটগুলি সিঙ্ক্রোনাইজ করা হয় না। প্রতিটি থ্রেডের জন্য পৃথক ফর্ম্যাট উদাহরণ তৈরি করার পরামর্শ দেওয়া হয়। যদি একাধিক থ্রেড একই সাথে একটি বিন্যাসে অ্যাক্সেস করে তবে অবশ্যই এটি বাহ্যিকভাবে সিঙ্ক্রোনাইজ করা উচিত।

এর অর্থ ধরুন আপনার কাছে ডেটফর্ম্যাট অবজেক্ট রয়েছে এবং আপনি দুটি ভিন্ন থ্রেড থেকে একই অবজেক্টটি অ্যাক্সেস করছেন এবং আপনি সেই অবজেক্টের উপর ফর্ম্যাট পদ্ধতিটি কল করছেন যে উভয় থ্রেড একই বস্তুতে একই সময়ে একই পদ্ধতিতে প্রবেশ করবে যাতে আপনি এটি জিতে ভিজ্যুয়ালাইজ করতে পারবেন সঠিক ফলাফলের ফলাফল নেই t

আপনার যদি ডেটফর্ম্যাট নিয়ে কোনওভাবে কাজ করতে হয় তবে আপনার কিছু করা উচিত

public synchronized myFormat(){
// call here actual format method
}

1

ডেটা দূষিত হয়। গতকাল আমি এটি আমার মাল্টিথ্রিড প্রোগ্রামে লক্ষ্য করেছি যেখানে আমার স্থির DateFormatবস্তু ছিল এবং এটির format()জন্য জেডিবিসি-র মাধ্যমে পড়া মূল্যবোধের জন্য ডেকে আছি । আমার এসকিউএল সিলেক্ট স্টেটমেন্ট ছিল যেখানে আমি একই তারিখটি বিভিন্ন নামের ( SELECT date_from, date_from AS date_from1 ...) সহ পড়ি । এই জাতীয় বিবৃতি WHEREবিবাদে বিভিন্ন তারিখের জন্য 5 টি থ্রেডে ব্যবহার করছিল। তারিখগুলি "স্বাভাবিক" দেখায় তবে তারা মানের সাথে পৃথক হয় - যখন সমস্ত তারিখ একই বছর থেকে ঘটেছিল কেবল মাস এবং দিন পরিবর্তিত হয়।

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


1

ফর্ম্যাট, নাম্বার ফর্ম্যাট, তারিখফর্ম্যাট, বার্তা ফর্ম্যাট ইত্যাদির স্পেসিফিকেশন থ্রেড-সেফ করার জন্য ডিজাইন করা হয়নি। এছাড়াও, পার্স পদ্ধতিটি পদ্ধতিতে কল করে Calendar.clone()এবং এটি ক্যালেন্ডারের পদচিহ্নগুলিকে প্রভাবিত করে তাই অনেকগুলি থ্রেড একই সাথে পার্স করা ক্যালেন্ডারের উদাহরণের ক্লোনিং পরিবর্তন করে।

আরো জানার জন্য, এই বাগ যেমন রিপোর্ট এই এবং এই , DateFormat থ্রেড-নিরাপত্তা সংখ্যার ফলাফল সঙ্গে।


1

সেরা উত্তরে ডগবনে parseফাংশন এবং এটির দিকে পরিচালিত করার উদাহরণ দেয়। নীচে একটি কোড রয়েছে যা আপনাকে formatফাংশনটি পরীক্ষা করতে দেয়।

লক্ষ্য করুন যে আপনি নির্বাহকের সংখ্যা (সমবর্তী থ্রেড) পরিবর্তন করলে আপনি বিভিন্ন ফলাফল পাবেন results আমার পরীক্ষাগুলি থেকে:

  • newFixedThreadPool5 এ ছেড়ে দিন এবং লুপটি প্রতিবার ব্যর্থ হবে।
  • 1 এ সেট করুন এবং লুপটি সর্বদা কাজ করবে (স্পষ্টতই সমস্ত কার্য এক সাথে এক হিসাবে চালিত হয়)
  • 2 এ সেট করুন এবং লুপটিতে প্রায় 6% কাজ করার সুযোগ রয়েছে।

আমি আপনার প্রসেসরের উপর নির্ভর করে ওয়াইএমএমভি অনুমান করছি।

formatফাংশন একটি ভিন্ন থ্রেড থেকে সময় বিন্যাস দ্বারা ব্যর্থ। এর কারণ অভ্যন্তরীণভাবে formatফাংশনটি calendarঅবজেক্ট ব্যবহার করে যা formatফাংশনের শুরুতে সেট আপ করা হয় । এবং calendarঅবজেক্টটি SimpleDateFormatশ্রেণীর সম্পত্তি । দীর্ঘশ্বাস...

/**
 * Test SimpleDateFormat.format (non) thread-safety.
 *
 * @throws Exception
 */
private static void testFormatterSafety() throws Exception {
    final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    final Calendar calendar1 = new GregorianCalendar(2013,1,28,13,24,56);
    final Calendar calendar2 = new GregorianCalendar(2014,1,28,13,24,56);
    String expected[] = {"2013-02-28 13:24:56", "2014-02-28 13:24:56"};

    Callable<String> task1 = new Callable<String>() {
        @Override
        public String call() throws Exception {
            return "0#" + format.format(calendar1.getTime());
        }
    };
    Callable<String> task2 = new Callable<String>() {
        @Override
        public String call() throws Exception {
            return "1#" + format.format(calendar2.getTime());
        }
    };

    //pool with X threads
    // note that using more then CPU-threads will not give you a performance boost
    ExecutorService exec = Executors.newFixedThreadPool(5);
    List<Future<String>> results = new ArrayList<>();

    //perform some date conversions
    for (int i = 0; i < 1000; i++) {
        results.add(exec.submit(task1));
        results.add(exec.submit(task2));
    }
    exec.shutdown();

    //look at the results
    for (Future<String> result : results) {
        String answer = result.get();
        String[] split = answer.split("#");
        Integer calendarNo = Integer.parseInt(split[0]);
        String formatted = split[1];
        if (!expected[calendarNo].equals(formatted)) {
            System.out.println("formatted: " + formatted);
            System.out.println("expected: " + expected[calendarNo]);
            System.out.println("answer: " + answer);
            throw new Exception("formatted != expected");
        /**
        } else {
            System.out.println("OK answer: " + answer);
        /**/
        }
    }
    System.out.println("OK: Loop finished");
}

0

যদি একাধিক থ্রেডগুলি একক তারিখের ফর্ম্যাট দৃষ্টান্তটি অ্যাক্সেস / অ্যাক্সেস করে এবং সিঙ্ক্রোনাইজেশন ব্যবহার না করা থাকে তবে স্ক্র্যাম্বলড ফলাফল পাওয়া সম্ভব। এটি কারণ একাধিক অ-পারমাণবিক ক্রিয়াকলাপগুলি রাষ্ট্র পরিবর্তন করতে পারে বা মেমরিটিকে বেমানান দেখছে।


0

এটি আমার সাধারণ কোড যা দেখায় যে তারিখফর্ম্যাট থ্রেড নিরাপদ নয়।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class DateTimeChecker {
    static DateFormat df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
    public static void main(String args[]){
       String target1 = "Thu Sep 28 20:29:30 JST 2000";
       String target2 = "Thu Sep 28 20:29:30 JST 2001";
       String target3 = "Thu Sep 28 20:29:30 JST 2002";
       runThread(target1);
       runThread(target2);
       runThread(target3);
   }
   public static void runThread(String target){
       Runnable myRunnable = new Runnable(){
          public void run(){

            Date result = null;
            try {
                result = df.parse(target);
            } catch (ParseException e) {
                e.printStackTrace();
                System.out.println("Ecxfrt");
            }  
            System.out.println(Thread.currentThread().getName() + "  " + result);
         }
       };
       Thread thread = new Thread(myRunnable);

       thread.start();
     }
}

যেহেতু সমস্ত থ্রেড একই সিম্পলডেটফর্ম্যাট অবজেক্টটি ব্যবহার করছে, এটি নিম্নলিখিত ব্যতিক্রম ছোঁড়ে।

Exception in thread "Thread-0" Exception in thread "Thread-2" Exception in thread "Thread-1" java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at java.text.DigitList.getDouble(Unknown Source)
at java.text.DecimalFormat.parse(Unknown Source)
at java.text.SimpleDateFormat.subParse(Unknown Source)
at java.text.SimpleDateFormat.parse(Unknown Source)
at java.text.DateFormat.parse(Unknown Source)
at DateTimeChecker$1.run(DateTimeChecker.java:24)
at java.lang.Thread.run(Unknown Source)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at java.text.DigitList.getDouble(Unknown Source)
at java.text.DecimalFormat.parse(Unknown Source)
at java.text.SimpleDateFormat.subParse(Unknown Source)
at java.text.SimpleDateFormat.parse(Unknown Source)
at java.text.DateFormat.parse(Unknown Source)
at DateTimeChecker$1.run(DateTimeChecker.java:24)
at java.lang.Thread.run(Unknown Source)
java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at java.text.DigitList.getDouble(Unknown Source)
at java.text.DecimalFormat.parse(Unknown Source)
at java.text.SimpleDateFormat.subParse(Unknown Source)
at java.text.SimpleDateFormat.parse(Unknown Source)
at java.text.DateFormat.parse(Unknown Source)
at DateTimeChecker$1.run(DateTimeChecker.java:24)
at java.lang.Thread.run(Unknown Source)

তবে আমরা যদি বিভিন্ন বস্তুকে বিভিন্ন থ্রেডে পাস করি তবে কোডটি ত্রুটি ছাড়াই চলে।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class DateTimeChecker {
    static DateFormat df;
    public static void main(String args[]){
       String target1 = "Thu Sep 28 20:29:30 JST 2000";
       String target2 = "Thu Sep 28 20:29:30 JST 2001";
       String target3 = "Thu Sep 28 20:29:30 JST 2002";
       df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
       runThread(target1, df);
       df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
       runThread(target2, df);
       df = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
       runThread(target3, df);
   }
   public static void runThread(String target, DateFormat df){
      Runnable myRunnable = new Runnable(){
        public void run(){

            Date result = null;
            try {
                result = df.parse(target);
            } catch (ParseException e) {
                e.printStackTrace();
                System.out.println("Ecxfrt");
            }  
            System.out.println(Thread.currentThread().getName() + "  " + result);
         }
       };
       Thread thread = new Thread(myRunnable);

       thread.start();
   }
}

এগুলি ফলাফল।

Thread-0  Thu Sep 28 17:29:30 IST 2000
Thread-2  Sat Sep 28 17:29:30 IST 2002
Thread-1  Fri Sep 28 17:29:30 IST 2001

ওপিতে জিজ্ঞাসা করা হয়েছিল কেন এমনটি হয় পাশাপাশি কী ঘটে।
আদম

0

এই কারণ হবে ArrayIndexOutOfBoundsException

ভুল ফলাফল ছাড়াও এটি আপনাকে সময়ে সময়ে ক্রাশ দেবে। এটি আপনার মেশিনের গতির উপর নির্ভর করে; আমার ল্যাপটপে, এটি একবারে 10,000,000 কলে একবার হয়:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

ExecutorService executorService = Executors.newFixedThreadPool(2);
Future<?> future1 = executorService.submit(() -> {
  for (int i = 0; i < 99000; i++) {
    sdf.format(Date.from(LocalDate.parse("2019-12-31").atStartOfDay().toInstant(UTC)));
  }
});

executorService.submit(() -> {
  for (int i = 0; i < 99000; i++) {
    sdf.format(Date.from(LocalDate.parse("2020-04-17").atStartOfDay().toInstant(UTC)));
  }
});

future1.get();

শেষ লাইন স্থগিতকারী নির্বাহকের ব্যতিক্রমটিকে ট্রিগার করে:

java.lang.ArrayIndexOutOfBoundsException: Index 16 out of bounds for length 13
  at java.base/sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:453)
  at java.base/java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2394)
  at java.base/java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2309)
  at java.base/java.util.Calendar.complete(Calendar.java:2301)
  at java.base/java.util.Calendar.get(Calendar.java:1856)
  at java.base/java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1150)
  at java.base/java.text.SimpleDateFormat.format(SimpleDateFormat.java:997)
  at java.base/java.text.SimpleDateFormat.format(SimpleDateFormat.java:967)
  at java.base/java.text.DateFormat.format(DateFormat.java:374)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.