জাভা থ্রেড অন্য সমস্ত থ্রেডকে একটি লুপে বাকী অপারেশন কার্যকর করে


123

নিম্নলিখিত কোড স্নিপেট দুটি থ্রেড চালায়, একটি হ'ল প্রতিটি টাইমারে সরল টাইমার লগিং, দ্বিতীয়টি একটি অসীম লুপ যা বাকী অপারেশন চালায়:

public class TestBlockingThread {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestBlockingThread.class);

    public static final void main(String[] args) throws InterruptedException {
        Runnable task = () -> {
            int i = 0;
            while (true) {
                i++;
                if (i != 0) {
                    boolean b = 1 % i == 0;
                }
            }
        };

        new Thread(new LogTimer()).start();
        Thread.sleep(2000);
        new Thread(task).start();
    }

    public static class LogTimer implements Runnable {
        @Override
        public void run() {
            while (true) {
                long start = System.currentTimeMillis();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // do nothing
                }
                LOGGER.info("timeElapsed={}", System.currentTimeMillis() - start);
            }
        }
    }
}

এটি নিম্নলিখিত ফলাফল দেয়:

[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=1004
[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=1003
[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=13331
[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=1006
[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=1003
[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=1004
[Thread-0] INFO  c.m.c.concurrent.TestBlockingThread - timeElapsed=1004

13.3 সেকেন্ডের জন্য কেন অসীম টাস্ক অন্য সমস্ত থ্রেড ব্লক করে দেয় তা আমি বুঝতে পারি না। আমি থ্রেডের অগ্রাধিকার এবং অন্যান্য সেটিংস পরিবর্তন করার চেষ্টা করেছি, কিছুই কার্যকর হয়নি।

এটি ঠিক করার জন্য আপনার কাছে যদি কোনও পরামর্শ থাকে (ওএস প্রসঙ্গের স্যুইচিং সেটিংস সহ টুইঙ্কিং) দয়া করে আমাকে জানান।


8
@ মার্থিন জিসি নয় এটি জেআইটি -XX:+PrintCompilationবর্ধিত দেরি শেষ হওয়ার সাথে সাথে আমি দৌড়ে
আন্দ্রেস

4
এটি আমার সিস্টেমে একমাত্র পরিবর্তনের সাথে সাথেই পুনরায় উত্পাদিত হয় আমি লগ কলকে System.out.println এর সাথে প্রতিস্থাপন করেছি। সময়সূচী ইস্যুর মতো মনে হয় কারণ আপনি যদি রান্নেবলের ভিতরে 1 মিমের ঘুমের পরিচয় দেন তবে (সত্য) লুপটি অন্য থ্রেডের বিরতিতে চলে যায়।
জেজেএফ

3
আমি এটির প্রস্তাব দিচ্ছি না, তবে আপনি যদি জেআইটি ব্যবহার করে অক্ষম করেন তবে -Djava.compiler=NONEতা হবে না।
Andreas

3
আপনি সম্ভবত একক পদ্ধতির জন্য জেআইটি অক্ষম করতে পারেন। একটি নির্দিষ্ট পদ্ধতি / শ্রেণীর জন্য জাভা জেআইটি অক্ষম
Andreas

3
এই কোডটিতে কোনও পূর্ণসংখ্যা বিভাগ নেই। আপনার শিরোনাম এবং প্রশ্ন ঠিক করুন।
মারকুইস অফ লর্ন

উত্তর:


94

এখানে সমস্ত ব্যাখ্যার পরে ( পিটার লরিকে ধন্যবাদ ) আমরা দেখতে পেয়েছি যে এই বিরতির মূল উত্সটি হ'ল লুপের অভ্যন্তরে সাফপয়েন্ট rarely

তবে আমি সিদ্ধান্ত নিয়েছি আরও গভীরতর হতে হবে এবং কেন নিরাপদ জায়গায় খুব কম পাওয়া যায়। আমি এটিকে কিছুটা বিভ্রান্ত করে দেখতে পেলাম যে whileলুপের পিছনের জাম্পটি এই ক্ষেত্রে "নিরাপদ" নয়।

তাই আমি -XX:+PrintAssemblyসাহায্য করার জন্য এর সমস্ত গৌরবতে ডেকে আছি

-XX:+UnlockDiagnosticVMOptions \
-XX:+TraceClassLoading \
-XX:+DebugNonSafepoints \
-XX:+PrintCompilation \
-XX:+PrintGCDetails \
-XX:+PrintStubCode \
-XX:+PrintAssembly \
-XX:PrintAssemblyOptions=-Mintel

কিছু তদন্তের পরে আমি দেখতে পেলাম যে C2ল্যাম্বদা সংকলক তৃতীয় পুনঃসংশোধনের পরে লুপের ভিতরে নিরাপদ পোলগুলি সম্পূর্ণভাবে ফেলে দিয়েছে।

হালনাগাদ

প্রোফাইলের পর্যায়ে চলকটি iকখনই 0 এর সমান দেখা যায় নি That's এজন্যই C2অনুমানমূলকভাবে এই শাখাটিকে অপ্টিমাইজ করা হয়েছে, যাতে লুপটি এমন কিছুতে রূপান্তরিত হয়েছিল why

for (int i = OSR_value; i != 0; i++) {
    if (1 % i == 0) {
        uncommon_trap();
    }
}
uncommon_trap();

নোট করুন যে মূলত অসীম লুপটি একটি কাউন্টার সহ একটি নিয়মিত সসীম লুপকে পুনরায় আকার দেওয়া হয়েছিল! সীমাবদ্ধ গণনা করা লুপগুলিতে সাফপয়েন্ট পোলগুলি নির্মূল করতে জেআইটি অপ্টিমাইজেশনের কারণে, এই লুপটিতে কোনও সাফপয়েন্ট পল ছিল না।

কিছুক্ষণ পরে, iআবার 0জড়িয়ে দেওয়া এবং অস্বাভাবিক ফাঁদ নেওয়া হয়েছিল। পদ্ধতিটি ডিওপিমাইজ করা হয়েছিল এবং দোভাষীগুলিতে চালিয়ে যাওয়া অব্যাহত ছিল। একটি নতুন জ্ঞানের সাথে পুনঃসংশোধনের সময় C2অসীম লুপটিকে স্বীকৃতি দেয় এবং সংকলন ত্যাগ করে। বাকী পদ্ধতিটি যথাযথ নিরাপদ বিন্দু নিয়ে দোভাষীতে এগিয়ে যায়।

নিতসান ওয়াকার্ট সেফপয়েন্টস এবং এই নির্দিষ্ট ইস্যুটির প্রচ্ছদ রচনা করে একটি দুর্দান্ত ব্লগ পোস্ট "সাফপয়েন্টস: অর্থ, পার্শ্ব প্রতিক্রিয়া এবং ওভারহেডস " রয়েছে

খুব দীর্ঘ গণনা করা লুপগুলিতে সাফপয়েন্টের নির্মূলকরণ একটি সমস্যা হিসাবে পরিচিত। বাগ JDK-5014723( ভ্লাদিমির ইভানভকে ধন্যবাদ ) এই সমস্যার সমাধান করে।

বাগ শেষ না হওয়া অবধি ওয়ার্কআরাউন্ড উপলব্ধ।

  1. ব্যবহার করে আপনি চেষ্টা করে দেখতে পারেন -XX:+UseCountedLoopSafepoints(এটা হবে সামগ্রিক কর্মক্ষমতা শাস্তি কারণ এবং জেভিএম ক্র্যাশ হতে পারে JDK-8161147 )। এটি ব্যবহারের পরে C2সংকলকটি পিছনের জাম্পে সাফপয়েন্টগুলি রাখা চালিয়ে যান এবং মূল বিরাম সম্পূর্ণরূপে অদৃশ্য হয়ে যায়।
  2. আপনি স্পষ্টভাবে ব্যবহার করে সমস্যাযুক্ত পদ্ধতির সংকলন অক্ষম করতে পারেন
    -XX:CompileCommand='exclude,binary/class/Name,methodName'

  3. অথবা আপনি নিজেই সেফপয়েন্টটি যোগ করে আপনার কোডটি পুনরায় লিখতে পারেন। উদাহরণস্বরূপ Thread.yield()চক্র শেষে কল বা এমনকি পরিবর্তন int iকরতে long i(ধন্যবাদ, Nitsan Wakart ) ও বিরতি ঠিক করবে।


7
এটি কীভাবে ঠিক করবেন এই প্রশ্নের সঠিক উত্তর ।
আন্দ্রেস

সতর্কতা: -XX:+UseCountedLoopSafepointsউত্পাদনে ব্যবহার করবেন না , যেহেতু এটি জেভিএমকে ক্র্যাশ করতে পারে । এখন অবধি সবচেয়ে ভাল কাজটি হ'ল লম্বা লুপটিকে সংক্ষিপ্ত আকারে ভাগ করা।
অপাঙ্গিন

@ পেংগিন আঃ বুঝেছি! আপনাকে ধন্যবাদ :) তাই c2সেফ সাফ পয়েন্টগুলি সরিয়ে দেয়! তবে আর একটি জিনিস যা আমি পাইনি তা হ'ল পরবর্তীটি যা চলছে। আমি যতদূর দেখতে পাচ্ছি লুপ আন্রোলিংয়ের পরে কোনও নিরাপদ বিন্দু নেই (?) এবং দেখে মনে হচ্ছে স্টু করার কোনও উপায় নেই। সুতরাং সেখানে এক ধরণের সময়সীমা ঘটে এবং ডি-অপ্টিমাইজেশন হয়?
vsminkov

2
আমার আগের মন্তব্যটি সঠিক ছিল না। এখন যা ঘটে তা সম্পূর্ণ পরিষ্কার। প্রোফাইলিং পর্যায়ে iকখনও 0 হয় না, সুতরাং লুপটি অনুমানমূলকভাবে for (int i = osr_value; i != 0; i++) { if (1 % i == 0) uncommon_trap(); } uncommon_trap();আই নিয়মিত সীমাবদ্ধ গণনা করা লুপের মতো কিছুতে রূপান্তরিত হয় । একবার i0-এ ফিরে আসে, অস্বাভাবিক ফাঁদ নেওয়া হয়, পদ্ধতিটি ডিওপিমাইজ করা হয় এবং দোভাষীতে এগিয়ে যায়। নতুন জ্ঞানের সাথে সংশোধনের সময় জেআইটি অসীম লুপকে স্বীকৃতি দেয় এবং সংকলন দেয়। পদ্ধতিটির বাকী অংশটি যথাযথ সেফপয়েন্টগুলির সাহায্যে দোভাষীতে সম্পাদন করা হয়।
আপনাঙ্গিন

1
আপনি কেবল কোন আইটি-এর পরিবর্তে আইএ দীর্ঘ করতে পারবেন, এটি লুপটিকে "আনসান্টেড" করে এবং সমস্যার সমাধান করবে।
নিতসান ওয়াকার্ট

64

সংক্ষেপে, আপনার কাছে লুপটি i == 0পৌঁছানো ছাড়া এটির ভিতরে কোনও নিরাপদ বিন্দু নেই । যখন এই পদ্ধতিটি সংকলন করা হয় এবং কোডটি প্রতিস্থাপনের জন্য ট্রিগার করা হয় তখন সমস্ত থ্রেডগুলি নিরাপদ বিন্দুতে আনতে হবে তবে এটি খুব দীর্ঘ সময় নেয়, কেবল কোড চালিত থ্রেডটিই নয়, জেভিএম-এর সমস্ত থ্রেড লক করে নেওয়া হয়।

আমি নিম্নলিখিত কমান্ড লাইনের বিকল্পগুলি যুক্ত করেছি।

-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintCompilation

আমি ভাসমান পয়েন্টটি ব্যবহার করতে কোডটিও সংশোধন করেছি যা বেশি সময় নেয় বলে মনে হচ্ছে।

boolean b = 1.0 / i == 0;

এবং আমি আউটপুটে যা দেখছি তা হ'ল

timeElapsed=100
Application time: 0.9560686 seconds
  41423  280 %     4       TestBlockingThread::lambda$main$0 @ -2 (27 bytes)   made not entrant
Total time for which application threads were stopped: 40.3971116 seconds, Stopping threads took: 40.3967755 seconds
Application time: 0.0000219 seconds
Total time for which application threads were stopped: 0.0005840 seconds, Stopping threads took: 0.0000383 seconds
  41424  281 %     3       TestBlockingThread::lambda$main$0 @ 2 (27 bytes)
timeElapsed=40473
  41425  282 %     4       TestBlockingThread::lambda$main$0 @ 2 (27 bytes)
  41426  281 %     3       TestBlockingThread::lambda$main$0 @ -2 (27 bytes)   made not entrant
timeElapsed=100

দ্রষ্টব্য: কোডটি প্রতিস্থাপনের জন্য, থ্রেডগুলি নিরাপদ স্থানে থামাতে হবে stopped তবে এটি এখানে উপস্থিত হয় যে এইরকম নিরাপদ বিন্দু খুব কমই পৌঁছে যায় (সম্ভবত কেবলমাত্র i == 0টাস্কে পরিবর্তন করার সময়)

Runnable task = () -> {
    for (int i = 1; i != 0 ; i++) {
        boolean b = 1.0 / i == 0;
    }
};

আমি একই বিলম্ব দেখতে পাচ্ছি।

timeElapsed=100
Application time: 0.9587419 seconds
  39044  280 %     4       TestBlockingThread::lambda$main$0 @ -2 (28 bytes)   made not entrant
Total time for which application threads were stopped: 38.0227039 seconds, Stopping threads took: 38.0225761 seconds
Application time: 0.0000087 seconds
Total time for which application threads were stopped: 0.0003102 seconds, Stopping threads took: 0.0000105 seconds
timeElapsed=38100
timeElapsed=100

লুপে কোডটি সাবধানে যুক্ত করা আপনার আরও দীর্ঘতর বিলম্ব হবে।

for (int i = 1; i != 0 ; i++) {
    boolean b = 1.0 / i / i == 0;
}

পায়

 Total time for which application threads were stopped: 59.6034546 seconds, Stopping threads took: 59.6030773 seconds

যাইহোক, একটি স্থানীয় পদ্ধতি ব্যবহারের জন্য কোডটি পরিবর্তন করুন যা সর্বদা একটি নিরাপদ পয়েন্ট থাকে (যদি এটি অভ্যন্তরীণ না হয়)

for (int i = 1; i != 0 ; i++) {
    boolean b = Math.cos(1.0 / i) == 0;
}

কপি করে প্রিন্ট

Total time for which application threads were stopped: 0.0001444 seconds, Stopping threads took: 0.0000615 seconds

দ্রষ্টব্য: if (Thread.currentThread().isInterrupted()) { ... }একটি লুপে যুক্ত করা একটি নিরাপদ বিন্দু যুক্ত করে।

দ্রষ্টব্য: এটি 16 টি কোর মেশিনে ঘটেছিল তাই সিপিইউ সংস্থার অভাব নেই।


1
সুতরাং এটি একটি JVM বাগ, ডান? যেখানে "বাগ" এর অর্থ কার্যকরকরণ সমস্যার তীব্র গুণমান এবং অনুমানের লঙ্ঘন নয়।
usr

1
@vsminkov সেফপয়েন্টের অভাবের কারণে কয়েক মিনিটের জন্য বিশ্বকে থামিয়ে দিতে সক্ষম হয়েছে বলে মনে হচ্ছে এটি বাগ হিসাবে ধরা উচিত। রানটাইম দীর্ঘ প্রতীক্ষা এড়াতে নিরাপদপয়েন্টগুলি প্রবর্তন করতে দায়ী।
ভু

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

9
@ খুব ভাল ... আমি যখন এই চিত্রটি পারফরম্যান্স অপ্টিমাইজেশনের কথা বলি তখনই আমি স্মরণ করি : ডি
ভস্মিনকভ

1
.NET এখানে সেফপয়েন্টগুলি সন্নিবেশ করায় (তবে .NET ধীরে ধীরে উত্পন্ন কোড রয়েছে)। একটি সম্ভাব্য সমাধান হ'ল লুপটি সঙ্কুচিত করা। দুটি লুপে বিভক্ত করুন, 1024 এলিমেন্টের ব্যাচ এবং বাইরের লুপ ড্রাইভ ব্যাচ এবং সেফপয়েন্টগুলির জন্য অভ্যন্তরটি যাচাই করে নিন। অনুশীলনে কম 1024x দ্বারা ধারণামূলকভাবে ওভারহেড কাটা uts
usr ডিরেক্টরির

26

কেন এর উত্তর খুঁজে পেয়েছি । এগুলিকে সেফপয়েন্টস বলা হয় এবং তারা জিসির কারণে ঘটে যাওয়া স্টপ-দ্য ওয়ার্ল্ড হিসাবে সর্বাধিক পরিচিত।

এই নিবন্ধগুলি দেখুন: লগিং স্টপ-দ্য ওয়ার্ল্ড জেভিএম-এ বিরাম দেয়

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

যে পয়েন্টগুলিতে অ্যাপ্লিকেশন থ্রেডগুলি নিরাপদে থামানো যেতে পারে তাদের ডাকা হয়, আশ্চর্য, নিরাপদ পয়েন্ট । এই শব্দটি প্রায়শই সমস্ত এসটিডাব্লু বিরতির উল্লেখ করতে ব্যবহৃত হয়।

এটি কম-বেশি সাধারণ যে সিসি লগগুলি সক্ষম। তবে এটি সমস্ত সেফপয়েন্টগুলিতে তথ্য ক্যাপচার করে না। এগুলি সব পেতে, এই JVM বিকল্পগুলি ব্যবহার করুন:

-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime

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

পড়া শর্তাদির হটস্পট শব্দকোষ , এটা এই করবেঃ

safepoint

প্রোগ্রাম কার্যকর করার সময় একটি পয়েন্ট যেখানে সমস্ত জিসি শিকড় জানা যায় এবং সমস্ত হিপ অবজেক্টের বিষয়বস্তু সামঞ্জস্যপূর্ণ। গ্লোবাল দৃষ্টিকোণ থেকে, সমস্ত থ্রেড অবশ্যই জিসি চালানোর আগে একটি সাফপয়েন্টে ব্লক করতে হবে। (একটি বিশেষ ক্ষেত্রে হিসাবে, জেএনআই কোড চলমান থ্রেডগুলি চালিয়ে যেতে পারে, কারণ তারা কেবলমাত্র হ্যান্ডলগুলি ব্যবহার করে a একটি সাফাইপয়েন্টের সময় তাদের অবশ্যই হ্যান্ডেলের সামগ্রীগুলি লোড করার পরিবর্তে অবরুদ্ধ করতে হবে)) স্থানীয় দৃষ্টিকোণ থেকে, একটি নিরাপদ অবস্থান একটি বিশিষ্ট বিন্দু কোডের একটি ব্লকে যেখানে এক্সিকিউটিভ থ্রেড জিসির জন্য ব্লক করতে পারে। বেশিরভাগ কল সাইটগুলি সেফপয়েন্ট হিসাবে যোগ্যতা অর্জন করে।এমন শক্তিশালী আক্রমণকারী রয়েছে যা প্রতিটি সেফপয়েন্টটিতে সত্য করে থাকে, যা অ-নিরাপদ বিন্দুতে উপেক্ষা করা যেতে পারে। সংকলিত জাভা কোড এবং সি / সি ++ কোড উভয়ই সাফপয়েন্টগুলির মধ্যে অপ্টিমাইজড হতে পারে তবে সেফপয়েন্টগুলিতে কম less জেআইটি সংকলক প্রতিটি সাফপয়েন্টে একটি জিসি মানচিত্র প্রেরণ করে। ভিএম-এর সি / সি ++ কোডটি সম্ভাব্য নিরাপদ অবস্থানগুলি চিহ্নিত করতে স্টাইলাইজড ম্যাক্রো-ভিত্তিক কনভেনশনগুলি (যেমন, ট্র্যাপস) ব্যবহার করে।

উপরে উল্লিখিত পতাকাগুলি নিয়ে চলমান, আমি এই আউটপুটটি পেয়েছি:

Application time: 0.9668750 seconds
Total time for which application threads were stopped: 0.0000747 seconds, Stopping threads took: 0.0000291 seconds
timeElapsed=1015
Application time: 1.0148568 seconds
Total time for which application threads were stopped: 0.0000556 seconds, Stopping threads took: 0.0000168 seconds
timeElapsed=1015
timeElapsed=1014
Application time: 2.0453971 seconds
Total time for which application threads were stopped: 10.7951187 seconds, Stopping threads took: 10.7950774 seconds
timeElapsed=11732
Application time: 1.0149263 seconds
Total time for which application threads were stopped: 0.0000644 seconds, Stopping threads took: 0.0000368 seconds
timeElapsed=1015

তৃতীয় এসটিডাব্লু ইভেন্টটি লক্ষ্য করুন:
মোট সময় বন্ধ হয়ে গেছে: 10.7951187 সেকেন্ড
থ্রেড থামানো সময় নিয়েছে: 10.7950774 সেকেন্ড

জেআইটি নিজেই কার্যত কোনও সময় নেয়নি, তবে একবার জেভিএম একটি জেআইটি সংকলন সম্পাদন করার সিদ্ধান্ত নিলে এটি এসটিডাব্লু মোডে প্রবেশ করেছে, যদিও কোডটি সংকলিত করার জন্য (অসীম লুপ) কোনও কল সাইট নেই , তাই কোনও নিরাপদ নিয়োগ পৌঁছে যায়নি।

এসটিডাব্লু শেষ হয় যখন জেআইটি শেষ পর্যন্ত অপেক্ষারত ছেড়ে দেয় এবং কোডটি অসীম লুপে পৌঁছায়।


"সাফপয়েন্ট - প্রোগ্রাম বাস্তবায়নের সময় এমন একটি পয়েন্ট যেখানে সমস্ত জিসি শিকড়গুলি জানা যায় এবং সমস্ত হিপ অবজেক্টের বিষয়গুলি সামঞ্জস্যপূর্ণ হয়" - স্থানীয় মানের ধরণের ভেরিয়েবলগুলি কেবল সেট / পাঠ করে এমন লুপে কেন এটি সত্য হবে না?
ব্লুরাজা - ড্যানি পিফ্লুঘোফিট

@ ব্লুরাজা-ড্যানি ফ্লুঘুফুট আমি আমার
vsminkov

5

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

তবে, যেহেতু আপনি কেবল এটি কীভাবে প্রতিরোধ করবেন জিজ্ঞাসা করেছেন, তাই আমার একটি সমাধান রয়েছে:

আপনার অসীম লুপটিকে এমন পদ্ধতিতে টানুন যেখানে এটি জেআইটি সংকলক থেকে বাদ দেওয়া যায়

public class TestBlockingThread {
    private static final Logger LOGGER = Logger.getLogger(TestBlockingThread.class.getName());

    public static final void main(String[] args) throws InterruptedException     {
        Runnable task = () -> {
            infLoop();
        };
        new Thread(new LogTimer()).start();
        Thread.sleep(2000);
        new Thread(task).start();
    }

    private static void infLoop()
    {
        int i = 0;
        while (true) {
            i++;
            if (i != 0) {
                boolean b = 1 % i == 0;
            }
        }
    }

এই ভিএম যুক্তি দিয়ে আপনার প্রোগ্রামটি চালান:

-এক্সএক্স: কমাইল কম্যান্ড = বাদ, প্যাকেজ.টেষ্টব্লকিং ট্র্যাড :: ইনফ্লুপ (আপনার প্যাকেজের তথ্য দিয়ে প্যাককে প্রতিস্থাপন করুন)

পদ্ধতিটি যখন জেআইটি-সংকলন করা হত তা নির্দেশ করার জন্য আপনার এই জাতীয় বার্তা পাওয়া উচিত:
### সংকলন বাদে: স্ট্যাটিক ব্লকিং est টেস্টব্লকিং ট্র্যাড :: ইনফ্লুপ
আপনি খেয়াল করতে পারেন যে আমি ক্লাসটিকে ব্লকিং বলে একটি প্যাকেজে রেখেছি


1
সংকলকটি বেশি সময় নিচ্ছে না, সমস্যাটি কোডটি কোনও নিরাপদ বিন্দুতে i == 0
পৌঁছছে

@ পিটারলাউরে কিন্তু whileলুপে চক্রের সমাপ্তি কেন একটি নিরাপদ নয়?
বনাম্মিকভ

@vsminkov- এ দেখা যাচ্ছে সেখানে একটি নিরাপদ পদক্ষেপ রয়েছে if (i != 0) { ... } else { safepoint(); }তবে এটি খুব বিরল। অর্থাত। আপনি যদি লুপ থেকে প্রস্থান / ব্রেক করেন তবে আপনি একই সময় পাবেন।
পিটার লরে

@ পিটারলাউরে কিছুটা তদন্তের পরে আমি দেখতে পেলাম যে লুপের পিছনের জাম্পে একটি সাফাইপয়েন্ট তৈরি করা একটি সাধারণ অনুশীলন। আমি শুধু কৌতূহলী এই বিশেষ ক্ষেত্রে পার্থক্য কি। সম্ভবত আমি নির্বোধ কিন্তু পিছনে ঝাঁপ "নিরাপদ" না হওয়ার কোনও কারণ আমি দেখতে পাই না
vsminkov

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