থ্রেড তৈরি করা কেন ব্যয়বহুল বলে?


180

জাভা টিউটোরিয়ালগুলি বলে যে একটি থ্রেড তৈরি করা ব্যয়বহুল। তবে কেন এটি ব্যয়বহুল? একটি জাভা থ্রেড তৈরি হওয়ার পরে ঠিক কী ঘটছে যা এর সৃষ্টি ব্যয়বহুল করে তোলে? আমি বিবৃতিটিকে সত্য হিসাবে নিচ্ছি, তবে আমি কেবল জেভিএম-তে থ্রেড তৈরির যান্ত্রিকগুলিতে আগ্রহী।

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

অনুশীলনে জাভা
কনকুরન્સી থেকে ব্রায়ান গোয়েটস, টিম পিয়েরেলস, জোশুয়া ব্লচ, জোসেফ বোভির, ডেভিড হোমস, ডগ লিও
প্রিন্ট ISBN-10: 0-321-34960-1


আপনি যে টিউটোরিয়ালগুলি পড়েছেন সে প্রসঙ্গে আমি জানিনা: তারা কি বোঝায় যে সৃষ্টিটি নিজেই ব্যয়বহুল, বা "থ্রেড তৈরি করা" ব্যয়বহুল। আমি যে পার্থক্যটি দেখানোর চেষ্টা করছি তা থ্রেডটি তৈরি করার খাঁটি কর্মের (এটি এটিকে তাত্ক্ষণিকভাবে বলুন বা এটি কিছু বলে দিন) বা আপনার কাছে একটি থ্রেড রয়েছে (তাই একটি থ্রেড ব্যবহার করে: সম্ভবত ওভারহেড থাকা)। কোনটি দাবি করা হয়েছে // আপনি কোনটির বিষয়ে জানতে চান?
Nanne

9
@typoknig - একটি নতুন থ্রেড তৈরি না করার তুলনায় ব্যয়বহুল :)
উইলকোডেজাভাফুডফুড


1
জয়ের জন্য থ্রেডপুল কাজের জন্য সর্বদা নতুন থ্রেড তৈরি করার দরকার নেই।
আলেকজান্ডার মিলস

উত্তর:


149

জাভা থ্রেড তৈরি করা ব্যয়বহুল কারণ এখানে মোটামুটি কাজ জড়িত রয়েছে:

  • থ্রেড স্ট্যাকের জন্য মেমরির একটি বিশাল ব্লক বরাদ্দ করতে হবে এবং আরম্ভ করতে হবে।
  • হোস্ট ওএসের সাথে নেটিভ থ্রেড তৈরি / নিবন্ধ করার জন্য সিস্টেম কল করা দরকার।
  • বর্ণনাকারীদের জেভিএম-অভ্যন্তরীণ ডেটা স্ট্রাকচারে তৈরি করা, আরম্ভ করা এবং যুক্ত করা দরকার।

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

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


একটি গুগল অনুসন্ধান আমাকে একটি পুরানো বেঞ্চমার্ক খুঁজে পেয়েছিল যা ২০০২ ভিনটেজ লিনাক্স চলমান ২০০ টি ভিনটেজ ডুয়াল প্রসেসর শিওনের উপর সান জাভা ১.৪.১ এ প্রতি সেকেন্ডে 000 4000 এর থ্রেড তৈরির হারের প্রতিবেদন করে। আরও একটি আধুনিক প্ল্যাটফর্ম আরও ভাল নম্বর দেবে ... এবং আমি পদ্ধতিটির বিষয়ে মন্তব্য করতে পারি না ... তবে কমপক্ষে এটি ব্যালপার্ক দেয় যাতে থ্রেড তৈরির ব্যয়বহুলতা কতটা ব্যয়বহুল

পিটার লরির বেঞ্চমার্কিং ইঙ্গিত দেয় যে আজকের দিনে থ্রেড তৈরির বিষয়টি নিখুঁতভাবে দ্রুত গতিযুক্ত, তবে এটি জাভা এবং / বা ওএস ... বা উচ্চতর প্রসেসরের গতির কারণে কতটা উন্নতি হয়েছে তা স্পষ্ট নয়। তবে আপনি যদি প্রতিবার একটি নতুন থ্রেড তৈরি / শুরু বনাম কোনও থ্রেড পুল ব্যবহার করেন তবে তার সংখ্যা এখনও 150+ গুণমানের উন্নতি নির্দেশ করে। (এবং তিনি বক্তব্য রেখেছিলেন যে এটি সমস্ত আপেক্ষিক ...)


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


জাভা থ্রেডের স্ট্যাক কীভাবে বরাদ্দ পেয়েছে তা দেখার জন্য আমি কিছুটা খনন করেছি। লিনাক্সে ওপেনজেডকে 6 এর ক্ষেত্রে, থ্রেড স্ট্যাকটি কল pthread_createকরে দেশীয় থ্রেড তৈরি করে বরাদ্দ করা হয় । (জেভিএম pthread_createপূর্বনির্ধারিত স্ট্যাকটি পাস করে না ))

তারপরে, pthread_createস্ট্যাকের মধ্যে নীচে একটি কল দ্বারা বরাদ্দ mmapকরা হয়েছে:

mmap(0, attr.__stacksize, 
     PROT_READ|PROT_WRITE|PROT_EXEC, 
     MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)

অনুসারে man mmap, MAP_ANONYMOUSপতাকাটি স্মৃতি শূন্যের সূচনা করে দেয়।

সুতরাং, যদিও এটি অপরিহার্য নাও হতে পারে যে নতুন জাভা থ্রেড স্ট্যাকগুলি শূন্য করা হয়েছে (জেভিএম স্পেস অনুসারে), অনুশীলনে (লিনাক্সে কমপক্ষে ওপেনজেডকে 6 দিয়ে) সেগুলি শূন্য করা হয়েছে।


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

2
"কোথাও কোথাও, কিছু (যেমন জিসি, বা ওএস) বাইটগুলি শূন্য করবে"। এটা হবে? সুরক্ষার কারণে ওএসের যদি নতুন মেমরি পৃষ্ঠার বরাদ্দ প্রয়োজন হয় will তবে তা অস্বাভাবিক হবে। এবং ওএস ইতিমধ্যে শূন্য-এড পৃষ্ঠাগুলির একটি ক্যাশে রাখতে পারে (আইআইআরসি, লিনাক্স এটি করে)। জিসিএম যে কোনও জাভা প্রোগ্রামকে এর বিষয়বস্তু পড়তে বাধা দেবে, তা কেন জিসি বিরক্ত করবেন? নোট করুন যে স্ট্যান্ডার্ড সি malloc()ফাংশন, যা জেভিএম ভালভাবে ব্যবহার করতে পারে, গ্যারান্টি দেয় না যে বরাদ্দ হওয়া মেমরি শূন্য-এড (সম্ভবত এ জাতীয় পারফরম্যান্স সমস্যা এড়াতে)।
রায়েদওয়াল্ড

1
stackoverflow.com/questions/2117072/… সম্মতি দেয় যে "প্রতিটি থ্রেডে বরাদ্দ করা স্ট্যাক মেমরির একটি প্রধান কারণ" factor
রায়েডওয়াল্ড

2
@ রেয়েডওয়াল্ড - স্ট্যাকটি আসলে কীভাবে বরাদ্দ করা হয় সে সম্পর্কিত তথ্যের জন্য আপডেট উত্তর দেখুন।
স্টিফেন সি

2
এটি সম্ভব (সম্ভাব্য এমনকি) যে mmap()কলটি বরাদ্দ করা মেমরি পৃষ্ঠাগুলি একটি শূন্য পৃষ্ঠায় অনুলিপি দ্বারা অনুলিপি করা হয়, তাই তাদের সূচনাটি নিজের মধ্যেই হয় না mmap(), তবে পৃষ্ঠাগুলি প্রথমে লিখিত হয় এবং তারপরে কেবলমাত্র একটি পৃষ্ঠায় থাকে একটি সময়. এটি হ'ল, থ্রেডটি নির্বাহী থ্রেডের পরিবর্তে তৈরি থ্রেডের দ্বারা বহন করা ব্যয় সহ কার্যকর করা শুরু করবে।
রায়েদওয়াল্ড

76

থ্রেডিংয়ের ব্যয়গুলি কোথা থেকে আসে তা নিয়ে আলোচনা করেছেন Others এই উত্তরটি ক্রেডিট তৈরি করা অনেক অপারেশনের তুলনায় ব্যয়বহুল নয়, তবে টাস্ক এক্সিকিউশন বিকল্পগুলির তুলনায় তুলনামূলকভাবে ব্যয়বহুল, যা তুলনামূলকভাবে কম ব্যয়বহুল covers

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

আরেকটি বিকল্প হ'ল থ্রেড পুল ব্যবহার করা। একটি থ্রেড পুল দুটি কারণে আরও দক্ষ হতে পারে। 1) এটি ইতিমধ্যে তৈরি করা থ্রেডগুলি পুনরায় ব্যবহার করে। 2) আপনার সর্বোত্তম পারফরম্যান্স রয়েছে তা নিশ্চিত করতে আপনি থ্রেডের সংখ্যা টিউন / নিয়ন্ত্রণ করতে পারেন।

নিম্নলিখিত প্রোগ্রাম প্রিন্ট ....

Time for a task to complete in a new Thread 71.3 us
Time for a task to complete in a thread pool 0.39 us
Time for a task to complete in the same thread 0.08 us
Time for a task to complete in a new Thread 65.4 us
Time for a task to complete in a thread pool 0.37 us
Time for a task to complete in the same thread 0.08 us
Time for a task to complete in a new Thread 61.4 us
Time for a task to complete in a thread pool 0.38 us
Time for a task to complete in the same thread 0.08 us

এটি একটি তুচ্ছ কাজের জন্য একটি পরীক্ষা যা প্রতিটি থ্রেডিং বিকল্পের ওভারহেড প্রকাশ করে। (এই পরীক্ষার টাস্কটি হ'ল বর্তমান থ্রেডে সর্বোত্তমভাবে সম্পাদিত টাস্কটি)

final BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>();
Runnable task = new Runnable() {
    @Override
    public void run() {
        queue.add(1);
    }
};

for (int t = 0; t < 3; t++) {
    {
        long start = System.nanoTime();
        int runs = 20000;
        for (int i = 0; i < runs; i++)
            new Thread(task).start();
        for (int i = 0; i < runs; i++)
            queue.take();
        long time = System.nanoTime() - start;
        System.out.printf("Time for a task to complete in a new Thread %.1f us%n", time / runs / 1000.0);
    }
    {
        int threads = Runtime.getRuntime().availableProcessors();
        ExecutorService es = Executors.newFixedThreadPool(threads);
        long start = System.nanoTime();
        int runs = 200000;
        for (int i = 0; i < runs; i++)
            es.execute(task);
        for (int i = 0; i < runs; i++)
            queue.take();
        long time = System.nanoTime() - start;
        System.out.printf("Time for a task to complete in a thread pool %.2f us%n", time / runs / 1000.0);
        es.shutdown();
    }
    {
        long start = System.nanoTime();
        int runs = 200000;
        for (int i = 0; i < runs; i++)
            task.run();
        for (int i = 0; i < runs; i++)
            queue.take();
        long time = System.nanoTime() - start;
        System.out.printf("Time for a task to complete in the same thread %.2f us%n", time / runs / 1000.0);
    }
}
}

আপনি দেখতে পাচ্ছেন যে একটি নতুন থ্রেড তৈরি করতে কেবল ~ 70। খরচ হয়। এটি বেশিরভাগ ক্ষেত্রেই তুচ্ছ হিসাবে বিবেচিত হতে পারে, তবে বেশিরভাগ ক্ষেত্রেই ব্যবহারের ক্ষেত্রে নয়। তুলনামূলকভাবে বলতে গেলে এটি বিকল্পগুলির চেয়ে বেশি ব্যয়বহুল এবং কিছু পরিস্থিতিতে থ্রেড পুল বা থ্রেড ব্যবহার না করা একটি ভাল সমাধান।


8
এটি সেখানে কোডের একটি দুর্দান্ত অংশ। সংক্ষিপ্ত, বিন্দুতে এবং স্পষ্টভাবে এর সংকীর্ণ প্রদর্শন করে।
নিকোলাস

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

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

প্রকৃতপক্ষে, কেন এটি নিয়মিতভাবে কিছু করা উচিত নয়, যেমন কাউন্টার বাড়ানোর মতো; পুরো ব্লকিংকিউ জিনিসটি ফেলে দিন।
সংযোজনকারীকে

@ গ্রাজি আপনি এক্ষেত্রে এটি করতে পারতেন তবে আপনি বেশিরভাগ বাস্তববাদী ক্ষেত্রে যেমন কাউন্টারে অপেক্ষা করা অক্ষম হতে পারে তেমনটি করেন না। যদি আপনি এটি করেন তবে উদাহরণগুলির মধ্যে পার্থক্য আরও বেশি হবে।
পিটার লরে

31

তত্ত্বগতভাবে, এটি জেভিএমের উপর নির্ভর করে। অনুশীলনে, প্রতিটি থ্রেডের তুলনামূলকভাবে প্রচুর পরিমাণে স্ট্যাক মেমরি থাকে (256 কেবি ডিফল্ট হিসাবে, আমার মনে হয়)। অতিরিক্তভাবে, থ্রেডগুলি ওএস থ্রেড হিসাবে প্রয়োগ করা হয়, সুতরাং এগুলি তৈরি করা একটি ওএস কল, অর্থাত্ একটি প্রসঙ্গে সুইচ জড়িত।

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


9
বিটিডব্লু কেবি = কিলো-বিট, কেবি = কিলো বাইট। জিবি = গিগা বিট, জিবি = গিগা বাইট।
পিটার ল্যারি

@ পিটারলাউরে আমরা কি 'কেবি' এবং 'কেবি' তে 'কে' কে মূলধন করি, তাই 'জিবি' এবং 'জিবি' এর প্রতিসাম্য আছে কি? এই জিনিস আমাকে বাগ।
জ্যাক

3
@Jack একটা হল K= 1024 এবং k); = 1000. en.wikipedia.org/wiki/Kibibyte
পিটার Lawrey

9

দুই ধরণের থ্রেড রয়েছে:

  1. সঠিক থ্রেড : এগুলি অন্তর্নিহিত অপারেটিং সিস্টেমের থ্রেডিং সুবিধার চারপাশে বিমূর্ততা। থ্রেড তৈরি করা সিস্টেমের মতোই ব্যয়বহুল - সর্বদা একটি ওভারহেড থাকে।

  2. "সবুজ" থ্রেড : জেভিএম দ্বারা নির্মিত এবং নির্ধারিত, এগুলি সস্তা, তবে সঠিক প্যারালাইলেজম হয় না। এগুলি থ্রেডের মতো আচরণ করে তবে ওএসের জেভিএম থ্রেডের মধ্যেই কার্যকর করা হয়। এগুলি প্রায়শই আমার জ্ঞানে ব্যবহৃত হয় না।

থ্রেড-ক্রিয়েশন ওভারহেডে আমি যে বৃহত্তম ফ্যাক্টরটিটি ভাবতে পারি তা হ'ল আপনার থ্রেডগুলির জন্য আপনি স্ট্যাক-আকারটি নির্ধারণ করেছেন। ভিএম চালানোর সময় থ্রেড স্ট্যাক-আকার পরামিতি হিসাবে পাস করা যেতে পারে।

এটি বাদে, থ্রেড তৈরি করা বেশিরভাগই ওএস-নির্ভর, এমনকি ভিএম-বাস্তবায়ন-নির্ভর।

এখন, আমি একটি বিষয় উল্লেখ করব: আপনি যদি প্রতি রানটাইমের প্রতিটি সেকেন্ডে প্রতি সেকেন্ডে 2000 থ্রেড ফায়ার করার পরিকল্পনা করছেন তবে থ্রেড তৈরি করা ব্যয়বহুল জেভিএম এটি পরিচালনা করার জন্য ডিজাইন করা হয়নি । আপনার যদি এমন কয়েকজন স্থিতিশীল কর্মী থাকে যা বরখাস্ত করা হবে না এবং বার বার মারা যাবে না, শিথিল করুন।


19
"... কয়েকজন স্থিতিশীল কর্মী যাদের বরখাস্ত করা হবে না এবং হত্যা করা হবে না ..." কেন আমি কর্মক্ষেত্রের পরিস্থিতি নিয়ে ভাবতে শুরু করেছিলাম? :-)
স্টিফেন সি

6

তৈরি করার Threadsজন্য ন্যায্য পরিমাণ মেমরি বরাদ্দ করা প্রয়োজন কারণ এটি একটি নয়, দুটি নতুন স্ট্যাক (জাভা কোডের জন্য একটি, নেটিভ কোডের জন্য একটি)। ব্যবহারের নির্বাহক / থ্রেড পুল জন্য একাধিক কর্ম জন্য থ্রেড পুনঃব্যবহার দ্বারা, ওভারহেড এড়াতে পারেন নির্বাহক


@ রেয়েডওয়াল্ড, আলাদা আলাদা স্ট্যাক ব্যবহার করা জেভিএম কী?
বেসসেস

1
ফিলিপ জেপি 2 টি স্ট্যাক বলে।
রায়েদওয়াল্ড

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

@ ফিলিপ জেএফ আপনি কি দয়া করে বিস্তারিত বলতে পারবেন? একটি জাভা কোডের জন্য একটি এবং নেটিভ কোডের জন্য একটি স্ট্যাকের দ্বারা কী বোঝাতে চান? এটার কাজ কি?
গুরিন্দার

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

1

স্পষ্টতই প্রশ্নটির ক্রুक्सটি 'ব্যয়বহুল' মানে কী।

একটি থ্রেড রান রান পদ্ধতির উপর ভিত্তি করে একটি স্ট্যাক তৈরি এবং স্ট্যাকটি আরম্ভ করার প্রয়োজন।

এটি নিয়ন্ত্রণ স্থিতি স্ট্রাকচার স্থাপন করতে হবে, অর্থাত্‍ এটি চলমান, অপেক্ষারত ইত্যাদি অবস্থায় কোন অবস্থায় রয়েছে set

এই জিনিসগুলি সেট আপ করার আশেপাশে খুব সম্ভবত একটি সুসংগত ব্যবস্থা আছে।

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