জাভাতে "চলমানযোগ্য প্রয়োগ করে" বনাম "প্রসারিত থ্রেড"


2118

জাভাতে থ্রেডের সাথে আমি যে সময়টি কাটিয়েছি, আমি থ্রেড লেখার এই দুটি উপায় খুঁজে পেয়েছি:

সহ implements Runnable:

public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

বা, এর সাথে extends Thread:

public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

এই দুটি ব্লকের কোডের কোনও উল্লেখযোগ্য পার্থক্য রয়েছে কি?


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

5
আপনি থ্রেড প্রসারিত করতে চান এমন একটি কারণ রয়েছে ( তবে আমি এটির প্রস্তাব দিই না ), আপনি প্রাকৃতিকভাবে পরিচালনা করতে পারেন interrupt()। আবার, এটি একটি ধারণা, এটি সঠিক ক্ষেত্রে কার্যকর হতে পারে, তবে আমি এটি প্রস্তাব করি না।
বেটসেস

এছাড়াও দয়া করে উত্তর দেখুন, চমত্কারভাবে ব্যাখ্যা করেছিলেন: stackoverflow.com/q/5562720/285594

@ বেস্টেস, আমি বাধা দেওয়ার চেষ্টা করছি আপনি বাধা () বাধা দেওয়ার বিষয়ে কী বোঝাতে পারেন। আপনি কি পদ্ধতিটিকে ওভাররাইড করার চেষ্টা করছেন?
বব ক্রস

8
হ্যাঁ, কোড অনুসারে ক্লাস থ্রেড এ যে কোনও শ্রেণি প্রসারিত করতে পারে তবে ক্লাস থ্রেড বি অন্য কোনও শ্রেণি প্রসারিত করতে পারে না
মণি গভীরভাবে

উত্তর:


1672

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

ইন ব্যবহারিক পদ, আপনার বাস্তবায়ন করতে পারে মানে Runnableএবং অন্য বর্গ থেকে পাশাপাশি প্রসারিত।


151
একদম ঠিক আছে। থ্রেডটি প্রসারিত করে আমরা কী আচরণটি ওভাররাইট করার চেষ্টা করছি? আমি যুক্তি দেব যে বেশিরভাগ লোকেরা কোনও আচরণকে ওভাররাইট করার চেষ্টা করছেন না, তবে থ্রেডের আচরণটি ব্যবহার করার চেষ্টা করছেন।
hooknc

87
একটি পার্শ্ব মন্তব্য হিসাবে, আপনি একটি থ্রেডে instantiate এবং তার শুরু () মেথড কল না আপনি জাভা <5 একটি মেমরি লিক তৈরি করছেন (এই Runnables সঙ্গে ঘটে না) যদি: stackoverflow.com/questions/107823/...
Nacho থেকে Coloma,

25
রান্নেবলের একটি সামান্য সুবিধা হ'ল, যদি কিছু নির্দিষ্ট পরিস্থিতিতে আপনি যত্ন নেন না বা থ্রেডিং ব্যবহার করতে না চান এবং আপনি কেবল কোডটি কার্যকর করতে চান তবে আপনার কাছে কেবল রান () কল করার বিকল্প রয়েছে। উদাহরণস্বরূপ (খুব হস্তবাহিত) if (numberCores > 4) myExecutor.excute(myRunnable); else myRunnable.run()
user949300

10
@ user949300 আপনি এটি দিয়েও করতে পারেন এবং extends Threadআপনি যদি থ্রেডিং করতে না চান তবে আপনি কেন প্রয়োগ করবেন Runnable...
m0skit0

30
সিয়েরা এবং বেটসকে প্যারাফ্রেজ করার জন্য, রান্নেবল বাস্তবায়নের মূল সুবিধা হ'ল আপনি "রানার" থেকে স্থাপত্যিকভাবে "কাজ" আলাদা করে দিচ্ছেন।
8bitjunkie

569

tl; dr: প্রয়োগসমূহ রান্নেবল আরও ভাল। তবে, সাবধানবাণী গুরুত্বপূর্ণ

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

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

ফলো-আপ: একটি আছে FutureTaskকন্সট্রাকটর আপনি Runnables ব্যবহার করবেন (যদি তোমার সাথে কি সবচেয়ে আরামদায়ক থাকবে) এবং এখনও আধুনিক সম্পাতবিন্দু সরঞ্জামের সুবিধা পেতে পারেন। জাভাডোকের উদ্ধৃতি দিতে :

আপনার যদি কোনও নির্দিষ্ট ফলাফলের প্রয়োজন না হয় তবে ফর্মটির নির্মাণকাজগুলি বিবেচনা করুন:

Future<?> f = new FutureTask<Object>(runnable, null)

সুতরাং, আমরা যদি তাদের runnableসাথে প্রতিস্থাপন করি তবে আমরা threadAনিম্নলিখিতটি পাই:

new FutureTask<Object>(threadA, null)

আরেকটি বিকল্প যা আপনাকে রানবেবলের কাছাকাছি থাকতে দেয় is একটি থ্রেডপুলএক্সেকিউটার । "ভবিষ্যতে কোনও সময় প্রদত্ত টাস্ক" সম্পাদন করতে আপনি রাননেবেলে পাস করার জন্য এক্সিকিউট পদ্ধতিটি ব্যবহার করতে পারেন ।

যদি আপনি কোনও থ্রেড পুল ব্যবহার করে দেখতে চান তবে উপরের কোড টুকরাটি নিম্নলিখিতগুলির মতো হয়ে উঠবে ( এক্সিকিউটার্স.নিউচ্যাচডথ্রেডপুল () কারখানা পদ্ধতি):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

40
এটি গ্রহণযোগ্য উত্তর আইএমএইচওর চেয়ে ভাল is একটি জিনিস: আপনার কোডের স্নিপেটটি নির্বাহককে বন্ধ করে দেয় না এবং আমি লক্ষ লক্ষ প্রশ্ন দেখি যেখানে লোকেরা এই ভুল হয়, প্রতিবার তারা কোনও কাজ স্প্যান করতে চাইলে একটি নতুন নির্বাহক তৈরি করে। esস্ট্যাটিক (বা ইনজেকশনের) ক্ষেত্র হিসাবে আরও ভাল হবে যাতে এটি কেবল একবার তৈরি হয়।
আর্টব্রিস্টল

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

3
আমি জানি যে আমি এই বিষয়ে মন্তব্য করতে কিছুটা দেরি করেছি, তবে FutureTaskসরাসরি কাজ করা সাধারণত আপনি যা করতে চান তা তা নয়। ExecutorServiceগুলি উপযুক্ত তৈরি করবে Futureযখন আপনি আপনার জন্য submitএকটি Runnable/ Callableতাদের। অনুরূপভাবে জন্য ScheduledExecutorServices এবং ScheduledFutureযখন আপনি scheduleএকটি Runnable/ Callable
পাওয়ারলর্ড

3
@ পাওয়ারলর্ড, আমার উদ্দেশ্য ছিল কোডের টুকরোগুলি তৈরি করা যা ওপি'র সাথে যতটা সম্ভব ঘনিষ্ঠভাবে মেলে। আমি সম্মত হই যে নতুন ফিউচারটাস্ক অনুকূল নয় তবে এটি ব্যাখ্যা করার উদ্দেশ্যে পরিষ্কার।
বব ক্রস

257

গল্পের শিক্ষা:

আপনি যদি কিছু আচরণকে ওভাররাইড করতে চান তবেই উত্তরাধিকারী করুন।

অথবা বরং এটি পড়তে হবে:

কম উত্তরাধিকারী, আরও ইন্টারফেস।


1
আপনি যদি একযোগে চলমান অবজেক্ট তৈরি করা শুরু করেন তবে সর্বদা এটি প্রশ্ন হওয়া উচিত! এমনকি আপনার কি থ্রেড অবজেক্ট ফ্যাশন দরকার?
লিবার্টি

4
থ্রেড থেকে উত্তরাধিকার সূত্রে, প্রায় সর্বদা run()পদ্ধতিটির আচরণকে ওভাররাইড করতে চায় ।
ওয়ারেন ডিউ

1
আপনি পদ্ধতিটিকে java.lang.Threadওভাররাইড করে কোনওটির আচরণকে ওভাররাইড করতে পারবেন না run()। সেক্ষেত্রে start()আমার অনুমান পদ্ধতিটি আপনাকে ওভাররাইড করতে হবে । সাধারণত আপনি পদ্ধতিতে java.lang.Threadআপনার এক্সিকিউশন ব্লক ইনজেকশনের মাধ্যমে আচরণের পুনরায় ব্যবহার করতে পারেন run()
সূরা

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

232

ভাল অনেক ভাল উত্তর, আমি এই আরও যোগ করতে চাই। এটি বুঝতে সাহায্য করবে Extending v/s Implementing Thread
দুটি ক্লাসের ফাইলগুলিকে খুব কাছ থেকে বেঁধে দেয় এবং কোড নিয়ে কাজ করার জন্য কিছুটা কঠিন হতে পারে।

উভয় পন্থা একই কাজ করে তবে কিছু পার্থক্য রয়েছে।
সবচেয়ে সাধারণ পার্থক্য হয়

  1. আপনি যখন থ্রেড ক্লাস প্রসারিত করেন, এর পরে আপনার প্রয়োজন মতো অন্য কোনও শ্রেণি প্রসারিত করতে পারবেন না। (যেমন আপনি জানেন, জাভা একাধিক শ্রেণীর উত্তরাধিকার সূত্রে অনুমতি দেয় না)।
  2. আপনি যখন রান্নেবল বাস্তবায়ন করেন, ভবিষ্যতে বা এখন অন্য কোনও ক্লাস বাড়ানোর জন্য আপনি আপনার শ্রেণির জন্য স্থান বাঁচাতে পারেন।

যাইহোক, চলমানযোগ্য এবং প্রসারিত থ্রেড বাস্তবায়নের মধ্যে একটি উল্লেখযোগ্য পার্থক্য হ'ল
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

নিম্নলিখিত উদাহরণটি আপনাকে আরও স্পষ্টভাবে বুঝতে সাহায্য করবে

//Implement Runnable Interface...
 class ImplementsRunnable implements Runnable {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ImplementsRunnable : Counter : " + counter);
 }
}

//Extend Thread class...
class ExtendsThread extends Thread {

private int counter = 0;

public void run() {
    counter++;
    System.out.println("ExtendsThread : Counter : " + counter);
 }
}

//Use the above classes here in main to understand the differences more clearly...
public class ThreadVsRunnable {

public static void main(String args[]) throws Exception {
    // Multiple threads share the same object.
    ImplementsRunnable rc = new ImplementsRunnable();
    Thread t1 = new Thread(rc);
    t1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t2 = new Thread(rc);
    t2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    Thread t3 = new Thread(rc);
    t3.start();

    // Creating new instance for every thread access.
    ExtendsThread tc1 = new ExtendsThread();
    tc1.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc2 = new ExtendsThread();
    tc2.start();
    Thread.sleep(1000); // Waiting for 1 second before starting next thread
    ExtendsThread tc3 = new ExtendsThread();
    tc3.start();
 }
}

উপরের প্রোগ্রামটির আউটপুট।

ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1

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

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

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

একটি ক্লাস যা রান্নেবল প্রয়োগ করে তা কোনও থ্রেড নয় এবং কেবল একটি শ্রেণি। একটি রান্নেবলকে থ্রেডে পরিণত হওয়ার জন্য আপনাকে থ্রেডের একটি উদাহরণ তৈরি করতে হবে এবং লক্ষ্য হিসাবে নিজেকে এড়িয়ে চলতে হবে।

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

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

আমি আশা করি এটি সাহায্য করবে!


40
আপনার কোডটি স্পষ্টতই ভুল। মানে, এটি যা করে তা করে, তবে আপনি যা দেখানোর ইচ্ছা করেছিলেন তা নয়।
zEro

38
স্পষ্ট করার জন্য: চলমান ক্ষেত্রে আপনি একাধিক থ্রেড শুরু করতে একই ইমপ্লিমেন্টস rnnable উদাহরণ ব্যবহার করেছেন, অন্যদিকে থ্রেডের ক্ষেত্রে আপনি বিভিন্ন এক্সটেন্ডসথ্রেড দৃষ্টান্ত তৈরি করছেন যা সম্ভবত আপনার আচরণের দিকে নিয়ে যায়। আপনার মূল পদ্ধতির ২ য় অর্ধেক হওয়া উচিত: ExtendsThread et = new ExtendsThread(); Thread tc1 = new Thread(et); tc1.start(); Thread.sleep(1000); Thread tc2 = new Thread(et); tc2.start(); Thread.sleep(1000); Thread tc3 = new Thread(et); tc3.start(); এটি কি আরও পরিষ্কার?
zEro

19
আমি এখনও আপনার অভিপ্রায় বুঝতে পারি নি, তবে আমার বক্তব্যটি হ'ল আপনি যদি এক্সটেন্ডসথ্রেডের একাধিক উদাহরণ তৈরি করেন - তবে তারা সকলে ফিরে আসবে (যেমন আপনি দেখিয়েছেন)। আপনি সেখানে একই কাজ করে রান্নেবলের জন্য একই ফলাফল পেতে পারেন, অর্থাত্ ইমপ্লিমেন্টআরনেবলের একাধিক উদাহরণ তৈরি করে।
zEro

3
@ জেরো হাই, আমি ভবিষ্যত থেকে এসেছি। আপনার কোডটির সংস্করণটিতেও বাড়ানো আছে Threadতা দেওয়া, বিবৃতিটি কি by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instanceতখন ভুল? যদি তা না হয়, তবে এটি এমন একটি মামলা যা এটি দেখায়?
এভিল ওয়াশিং মেশিন

4
এখানে পোস্ট করা কোডটি বিভ্রান্তিমূলক এবং মাথা ব্যথার কারণ হতে পারে। এটি কিছুটা সাফ করার জন্য @ জেরোকে ধন্যবাদ।
নিকস

78

আমি অবাক হয়েছি এমন একটি বিষয় এখনও উল্লেখ করা হয়নি যা হ'ল বাস্তবায়ন Runnableআপনার শ্রেণিকে আরও নমনীয় করে তোলে।

আপনি যদি থ্রেড প্রসারিত করেন তবে আপনি যে ক্রিয়াটি করছেন তা সর্বদা থ্রেডে থাকবে। তবে আপনি যদি Runnableএটি প্রয়োগ করেন তবে তা হওয়ার দরকার নেই। আপনি এটি কোনও থ্রেডে চালাতে পারেন, বা এটি কোনওরকম নির্বাহক পরিষেবাতে পাস করতে পারেন, বা কেবল একটি থ্রেডযুক্ত অ্যাপ্লিকেশনটির মধ্যে এটি একটি টাস্ক হিসাবে ঘুরিয়ে দিতে পারেন (সম্ভবত পরবর্তী সময়ে চালানো যেতে পারে তবে একই থ্রেডের মধ্যে)। Runnableআপনি নিজেকে বেঁধে রাখার চেয়ে যদি আপনি কেবল ব্যবহার করেন তবে বিকল্পগুলি অনেক বেশি খোলা থাকে Thread


6
ঠিক আছে, আপনি আসলে কোনও জিনিস দিয়ে একই জিনিসটি করতে পারেন Threadকারণ Thread implements Runnable… ;-) তবে Runnableএগুলি একটি দিয়ে না করার চেয়ে এই জিনিসগুলি করা "ভাল বোধ করে" Thread!
সিইগি

7
সত্য, তবে আপনার Threadপ্রচুর পরিমাণে অতিরিক্ত জিনিস যুক্ত করে যা আপনার প্রয়োজন হয় না এবং অনেক ক্ষেত্রেই তা চান না। আপনি আসলে যা করছেন তার সাথে মেলে এমন ইন্টারফেস প্রয়োগ করা আপনি সর্বদা ভাল।
হার্মস

74

আপনি যদি অন্য কোনও ক্লাস প্রয়োগ বা প্রসারিত করতে চান তবে Runnableইন্টারফেসটি সবচেয়ে বেশি পছন্দনীয়, অন্যথায়, আপনি যদি অন্য কোনও শ্রেণি প্রসারিত বা বাস্তবায়ন করতে না চান তবে Threadশ্রেণিটি পছন্দনীয়।

সবচেয়ে সাধারণ পার্থক্য হয়

এখানে চিত্র বর্ণনা লিখুন

আপনি যখন extends Threadক্লাস করেন, তার পরে আপনার প্রয়োজন মতো অন্য কোনও ক্লাস বাড়িয়ে দিতে পারবেন না। (যেমন আপনি জানেন, জাভা একাধিক শ্রেণীর উত্তরাধিকার সূত্রে অনুমতি দেয় না)।

আপনি যখন implements Runnableভবিষ্যতে বা এখন অন্য কোনও ক্লাস বাড়ানোর জন্য আপনার ক্লাসের জন্য স্থান সংরক্ষণ করতে পারেন।

  • জাভা একাধিক উত্তরাধিকারকে সমর্থন করে না, যার অর্থ আপনি জাভাতে কেবল একটি শ্রেণি প্রসারিত করতে পারেন তাই আপনি একবার থ্রেড ক্লাস প্রসারিত করার পরে আপনার সুযোগটি হারাতে পারেন এবং জাভাতে অন্য শ্রেণি প্রসারিত বা উত্তরাধিকারী করতে পারবেন না।

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

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

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

  • জাভা ডিজাইনার এটি স্বীকৃতি দেয় এবং এ কারণেই এক্সিকিউটাররা রান্নেবলকে টাস্ক হিসাবে স্বীকার করে এবং তাদের কর্মী থ্রেড রয়েছে যা সেই কার্যটি কার্যকর করে।

  • সমস্ত থ্রেড পদ্ধতি হেরেটিং কেবল কোনও টাস্ককে উপস্থাপনের জন্য অতিরিক্ত ওভারহেড যা রান্নেবলের সাহায্যে সহজেই করা যায়।

Javarevisited.blogspot.com থেকে সৌজন্যে

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

তবে, উল্লেখযোগ্য পার্থক্য।

আপনি যখন extends Threadক্লাস করেন, আপনার প্রতিটি থ্রেড একটি অনন্য বস্তু তৈরি করে এবং এর সাথে যুক্ত হবে। আপনি যখন implements Runnableএটি একাধিক থ্রেডে একই জিনিস ভাগ করে।


73

আসলে, তুলনা করা বুদ্ধিমানের কাজ নয় RunnableএবংThread একে অপরের সাথে।

এই দু'জনের যেমন মাল্টি-থ্রেডিংয়ের মধ্যে নির্ভরতা এবং সম্পর্ক রয়েছে Wheel and Engine মোটর গাড়ির সম্পর্কের ।

আমি বলব, দুটি ধাপে মাল্টি থ্রেডিংয়ের জন্য কেবল একটি উপায়। আমাকে আমার কথা বলতে দাও।

চলমান:
কার্যকর করার interface Runnableসময় এর অর্থ হল আপনি এমন কিছু তৈরি করছেন যা run ableভিন্ন থ্রেডে রয়েছে। এখন এমন কিছু তৈরি করা যা কোনও থ্রেডের ভিতরে চলতে পারে (থ্রেডের অভ্যন্তরে চলমান), এটি কোনও থ্রেড তৈরির অর্থ নয়।
সুতরাং ক্লাসটি MyRunnableএকটি void runপদ্ধতি সহ একটি সাধারণ শ্রেণি ছাড়া কিছুই নয় । এবং এটির অবজেক্টগুলি এমন কিছু সাধারণ অবজেক্ট runহবে যা কেবলমাত্র একটি পদ্ধতি যা ডাকা হলে সাধারণত সম্পাদিত হবে। (যতক্ষণ না আমরা বস্তুকে থ্রেডে পাস করি)।

থ্রেড:,
class Thread আমি বলব একটি নতুন থ্রেড শুরু করার সক্ষমতা সহ একটি খুব বিশেষ শ্রেণি যা প্রকৃতপক্ষে তার start()পদ্ধতির মাধ্যমে বহু-থ্রেডিং সক্ষম করে ।

তুলনামূলক বুদ্ধিমান কেন না?
কারণ মাল্টি থ্রেডিংয়ের জন্য আমাদের দু'জনেরই দরকার।

মাল্টি-থ্রেডিংয়ের জন্য আমাদের দুটি জিনিস দরকার:

  • থ্রেডের (দৌড়ানোর যোগ্য) অভ্যন্তরে দৌড়াতে পারে এমন কিছু।
  • এমন কিছু যা একটি নতুন থ্রেড (থ্রেড) শুরু করতে পারে।

সুতরাং প্রযুক্তিগতভাবে এবং তাত্ত্বিকভাবে উভয়কেই একটি থ্রেড শুরু করা প্রয়োজন, একটি চালাবে এবং একজন এটি চালাবেন ( Wheel and Engineমোটর গাড়ির মতো )।

এজন্য আপনি কোনও থ্রেড শুরু করতে পারবেন না MyRunnableএটির কোনও উদাহরণে আপনাকে এটি প্রেরণ করা প্রয়োজন Thread

তবে কেবল থ্রেড ব্যবহার করে একটি থ্রেড তৈরি করা এবং চালানো সম্ভব class Threadকারণ শ্রেণি Threadপ্রয়োগগুলি Runnableযাতে আমরা সকলেই জানি Threadএটি একটি Runnableঅভ্যন্তর।

পরিশেষে Threadএবং Runnableপ্রতিযোগী বা প্রতিস্থাপন নয় বহুবিশেষের জন্য একে অপরের পরিপূরক।


3
একদম ঠিক! এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। বিটিডাব্লু আমার মনে হয় প্রশ্নটি সম্পাদিত হয়েছে এবং ThreadAএর আর কোনও অর্থ নেই
ইডেলওয়াল

গৃহীত উত্তরটি আপনার প্রতিক্রিয়ার জন্য অনেক বেশি প্রতিনিধি ধন্যবাদ @ এডেলওয়াল
সাইফ

সেরা উত্তর! ধন্যবাদ!
মাইকেলওয়াই

44

আপনার রান্নেবল বাস্তবায়ন করা উচিত, তবে আপনি যদি জাভা 5 বা ততোধিক চলমান হন তবে আপনার এটি শুরু করা উচিত নয় new Threadবরং এর পরিবর্তে এক্সিকিউটার সার্ভিস ব্যবহার করা উচিত। বিশদগুলির জন্য দেখুন: জাভাতে সহজ থ্রেডিং কীভাবে প্রয়োগ করা যায়


5
আমি মনে করি না এক্সিকিউটর সার্ভিস সেই কার্যকর হবে যদি আপনি কেবল একটি একক থ্রেড চালু করতে চান।
পাওয়ারলর্ড

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

4
যে কোনও মাল্টি-থ্রেডিং ব্যবহারের মূল বিষয় যদি আমরা জানি যে এটি একক থ্রেড হতে চলেছে ri সুতরাং আসুন ধরে নেওয়া যাক আমাদের একাধিক থ্রেড রয়েছে এবং এই উত্তরটি মূল্যবান।
zEro

1
@ জেরো আমি নিশ্চিত যে কেবলমাত্র একটি ইভেন্টের পাঠানোর থ্রেডের একটি কারণ রয়েছে। আমি সন্দেহ করি এটি একমাত্র কেস ছিল আলাদা থ্রেড রাখা ভাল তবে একাধিক হওয়া সম্ভবত সেরা নয়।
পোরকোসফিনো

33

আমি বিশেষজ্ঞ নই, তবে থ্রেড প্রসারিত করার পরিবর্তে রান্নেবল বাস্তবায়নের একটি কারণ সম্পর্কে আমি ভাবতে পারি: জাভা কেবল একক উত্তরাধিকারকে সমর্থন করে, তাই আপনি কেবল একটি শ্রেণি প্রসারিত করতে পারেন।

সম্পাদনা: এটি প্রাথমিকভাবে বলেছিল "ইন্টারফেস প্রয়োগের জন্য কম সংস্থান দরকার" " পাশাপাশি, তবে আপনাকে নতুনভাবে একটি নতুন থ্রেড উদাহরণ তৈরি করতে হবে, সুতরাং এটি ভুল ছিল।


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

@ নাবেলথোবানী সাধারণ জাভা পাত্তা দিচ্ছে না তবে অ্যান্ড্রয়েডের মতো শোনাচ্ছে। যদিও আমি বলার মতো অ্যান্ড্রয়েডের সাথে যথেষ্ট পরিচিত নই।
পাওয়ারলর্ড

1
@ নাবিলথোবানি অবশ্যই আপনি পারবেন। সম্ভবত আপনি আপনার রানেবলের সাথে একটি থ্রেড তৈরি করছেন না।
m0skit0

20

আমি বলব তৃতীয় উপায় আছে:

public class Something {

    public void justAnotherMethod() { ... }

}

new Thread(new Runnable() {
   public void run() {
    instanceOfSomething.justAnotherMethod();
   }
}).start();

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


38
এটি আসলে তৃতীয় উপায় নয়। আপনি এখনও রান্নেবল বাস্তবায়ন করছেন, কেবল বেনামে এটি করছেন।
ডন রবি

2
@ ডন রবি: যা আলাদা। এটি প্রায়শই সুবিধাজনক এবং আপনি ক্লাস / পদ্ধতিযুক্ত ক্ষেত্র এবং ক্ষেত্র এবং চূড়ান্ত স্থানীয় ভেরিয়েবলগুলি ব্যবহার করতে পারেন।
বার্ট ভ্যান হিউকেলোম

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

18

জাভা 8 প্রকাশের সাথে সাথে এখন তৃতীয় বিকল্প রয়েছে।

Runnableএকটি কার্যকরী ইন্টারফেস , যার অর্থ লাম্বডা এক্সপ্রেশন বা পদ্ধতির উল্লেখগুলির সাথে এর উদাহরণগুলি তৈরি করা যেতে পারে।

আপনার উদাহরণটি এর সাথে প্রতিস্থাপন করা যেতে পারে:

new Thread(() -> { /* Code here */ }).start()

অথবা আপনি যদি কোনও ExecutorServiceএবং একটি পদ্ধতির উল্লেখ ব্যবহার করতে চান :

executor.execute(runner::run)

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


এই উত্তরের ব্যাখ্যা দরকার। কিছু বিস্ময়ের পরে, আমি উপসংহারে () -> {}পৌঁছেছি যে কারওর প্রয়োজন অনুসারে কাস্টম যুক্তি উপস্থাপন করা উচিত? তাহলে কি আরও ভাল বলা হবে () -> { /* Code here */ }?
টুলমেকারস্টেভ

17

একটি ইন্টারফেস ইনস্ট্যান্ট করা আপনার কোড এবং থ্রেডগুলির প্রয়োগের মধ্যে একটি পরিষ্কার বিচ্ছিন্নতা দেয়, তাই আমি এই ক্ষেত্রে রান্নেবল বাস্তবায়ন করতে পছন্দ করব।


12

এখানের প্রত্যেকেই মনে করছেন রান্নেবলকে বাস্তবায়ন করার উপায় এবং আমি তাদের সাথে সত্যিই একমত নই তবে আমার মতে থ্রেড প্রসারিত করার জন্য একটি মামলা রয়েছে, বাস্তবে আপনি এটি আপনার কোডটিতে সাজিয়েছেন।

আপনি যদি রান্নেবল বাস্তবায়ন করেন তবে রান্নেবল প্রয়োগকারী ক্লাসটির থ্রেড নামের উপর কোনও নিয়ন্ত্রণ নেই, এটি কলিং কোড যা থ্রেডের নামটি সেট করতে পারে, যেমন:

new Thread(myRunnable,"WhateverNameiFeelLike");

তবে আপনি যদি থ্রেড প্রসারিত করেন তবে আপনি ক্লাসের মধ্যেই এটি পরিচালনা করতে পারবেন (ঠিক যেমন উদাহরণ হিসাবে আপনি থ্রেডটির নাম রাখেন 'থ্রেডবি')। এই ক্ষেত্রে আপনি:

ক) এটি ডিবাগিং উদ্দেশ্যে আরও কার্যকর নাম দিতে পারে

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

আপনি এমনকি উদাহরণস্বরূপ এটির তৈরির স্ট্যাক ট্রেস নিতে পারেন এবং এটি থ্রেডের নাম হিসাবে ব্যবহার করতে পারেন। এটি অদ্ভুত মনে হতে পারে তবে আপনার কোডটি কীভাবে কাঠামোবদ্ধ করা হয়েছে তার উপর নির্ভর করে এটি ডিবাগিংয়ের উদ্দেশ্যে খুব কার্যকর হতে পারে।

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

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

কলিং স্ট্যাকটির নাম হিসাবে এটি জেনেরিক থ্রেডের একটি উদাহরণ:

public class DebuggableThread extends Thread {
    private static String getStackTrace(String name) {
        Throwable t= new Throwable("DebuggableThread-"+name);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(os);
        t.printStackTrace(ps);
        return os.toString();
    }

    public DebuggableThread(String name) {
        super(getStackTrace(name));
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new Thread());
        System.out.println(new DebuggableThread("MainTest"));
    }
}

এবং এখানে দুটি নামের সাথে তুলনা করে আউটপুটটির একটি নমুনা দেওয়া হয়েছে:

Thread[Thread-1,5,main]
Thread[java.lang.Throwable: DebuggableThread-MainTest
    at DebuggableThread.getStackTrace(DebuggableThread.java:6)
    at DebuggableThread.<init>(DebuggableThread.java:14)
    at DebuggableThread.main(DebuggableThread.java:19)
,5,main]

সিএইচও আপনার বক্তব্য কি? থ্রেড তৈরির স্ট্যাকট্রেস পেতে থ্রেডের সম্পাদনার সময় আপনি উপরের কোডটি ব্যবহার করতে পারেননি (পরিবর্তে আপনি একটি সাধারণ নাম পাবেন বা থ্রেড লঞ্চটির সর্বোত্তম স্ট্যাকট্রেস পাবেন) তবে থ্রেড সাবক্লাসিং করে আপনি ঠিক তা করতে পারেন এবং জোর করতে পারেন এটি এমনকি আরও প্রসঙ্গের নির্দিষ্ট তথ্যের প্রয়োজন হয় যার ফলে আপনাকে ঠিক কোন থ্রেডে সমস্যা হতে পারে তার আরও দৃ concrete় ধারণা প্রদান করে।
অ্যান্টনিএম

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

সুতোর নাম? থ্রেড শ্রেণীর পাশাপাশি আপনাকে প্রসারিত করার কিছুই থামছে না।
রিচিএইচএইচ

11

চলমান কারণ:

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

আপনার এখনই এগুলির কোনও প্রয়োজন না হলেও ভবিষ্যতেও হতে পারে। যেহেতু থ্রেডকে ওভাররাইড করার কোনও সুবিধা নেই, তাই রান্নেবল একটি আরও ভাল সমাধান।


11

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

  1. কার্যকারিতা যুক্ত করতে বা সংশোধন করার জন্য আপনি সাধারণত একটি শ্রেণি প্রসারিত করেন। সুতরাং, যদি আপনি না চান করতে ওভাররাইট কোন থ্রেড আচরণ , তারপর runnable ব্যবহার করুন।

  2. একই বিষয়ের আলোকে, আপনি প্রয়োজন হবে না করতে উত্তরাধিকারী থ্রেড পদ্ধতি, আপনি যে ছাড়া করতে পারেন ওভারহেড runnable ব্যবহার করে।

  3. একক উত্তরাধিকার : আপনি যদি থ্রেড প্রসারিত করেন তবে আপনি অন্য কোনও শ্রেণীর কাছ থেকে প্রসারিত করতে পারবেন না, তাই যদি আপনার এটি করা দরকার হয় তবে আপনাকে রান্নেবল ব্যবহার করতে হবে।

  4. এটা যে অর্থে এটি একটি runnable টাস্ক আছে ভাল প্রযুক্তিগত উপায়ে থেকে পৃথক ডোমেইন যুক্তিবিজ্ঞান ভালো নকশা, আলাদা আপনার থেকে টাস্ক আপনার রানার

  5. আপনি একই রান্নেবল অবজেক্টকে একাধিকবার এক্সিকিউট করতে পারেন , একটি থ্রেড অবজেক্ট তবে একবারেই শুরু করা যেতে পারে। (সম্ভবত কারণ, এক্সিকিউটাররা কেন রানবেলগুলি গ্রহণ করে তবে থ্রেডগুলি না।)

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

  7. এটি আপনার ইউনিট পরীক্ষায় টাস্ক-লজিক এবং সম্মতিযুক্ত দিকগুলি পৃথক করা সহজ করে তোলে ।

  8. আপনি যদি এই প্রশ্নে আগ্রহী হন তবে আপনার কলযোগ্য এবং রাননেবলের মধ্যে পার্থক্য সম্পর্কেও আগ্রহী হতে পারে ।


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

11

প্রসারিত থ্রেড এবং চলমানযোগ্য কার্যকরকরণের মধ্যে পার্থক্যগুলি হ'ল:

এখানে চিত্র বর্ণনা লিখুন


8

এটি ওরাকলসের সংজ্ঞায়িত এবং একটি থ্রেড টিউটোরিয়াল শুরু করার বিষয়ে আলোচনা করা হয়েছে :

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

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


8

এর সহজ ব্যাখ্যাটি বাস্তবায়নের মাধ্যমে হবে Runnableআমরা একই বস্তুকে একাধিক থ্রেড এবং প্রতিটিটিতে নির্ধারণ করতে পারিThread ভাগ একই বস্তুর অবস্থান ও আচরণ করে।

উদাহরণ হিসেবে বলা যায়, দুই থ্রেড, আছে অনুমান করা thread1 একটি অ্যারের রাখে একটি পূর্ণসংখ্যা এবং thread2 যখন অ্যারের ভরাট করা হয় অ্যারে থেকে পূর্ণসংখ্যার লাগে। লক্ষ্য করুন যে থ্রেড 2 কাজ করার জন্য এটি থ্রেড 1 পূরণ করেছে কিনা তা অ্যারের অবস্থা জানতে হবে to

বাস্তবায়ন Runnableআপনাকে অবজেক্টটি ভাগ করে নেওয়ার জন্য এই নমনীয়তা দেয় যেখানে extends Threadআপনি প্রতিটি থ্রেডের জন্য নতুন অবজেক্ট তৈরি করতে সক্ষম হন সুতরাং থ্রেড 1 দ্বারা করা কোনও আপডেট থ্রেড 2 এ হারিয়ে যায়।


7

আমি যদি ভুল না হয় তবে এটি কমবেশি এর সাথে মিল রয়েছে

একটি ইন্টারফেস এবং বিমূর্ত শ্রেণীর মধ্যে পার্থক্য কী?

" ইস এ " সম্পর্ক স্থাপন করে এবং ইন্টারফেস "এর একটি " ক্ষমতা দেয় Has

চলমানযোগ্য প্রয়োগগুলি পছন্দ করুন :

  1. যদি আপনার থ্রেড ক্লাস প্রসারিত করতে না হয় এবং থ্রেড এপিআই এর ডিফল্ট বাস্তবায়ন পরিবর্তন করতে হয়
  2. আপনি যদি একটি আগুন চালাচ্ছেন এবং আদেশটি ভুলে যান
  3. আপনি যদি ইতিমধ্যে অন্য শ্রেণি প্রসারিত করেন

পছন্দ " থ্রেড প্রসারিত ":

  1. যদি আপনাকে ওরাকল ডকুমেন্টেশন পৃষ্ঠাতে তালিকাভুক্ত হিসাবে এই থ্রেড পদ্ধতিগুলির কোনও ওভাররাইড করতে হয়

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

ভিন্ন নোটে, উন্নত ExecutorServiceবা ThreadPoolExecutorServiceএপিআই ব্যবহার করে আরও নমনীয়তা এবং নিয়ন্ত্রণ সরবরাহ করে।

এই এসই প্রশ্নটি দেখুন:

এক্সিকিউটর সার্ভিস বনাম ক্যাজুয়াল থ্রেড স্প্যানার


5

চলমানযোগ্য বাস্তবায়ন থেকে থ্রেড শ্রেণিকে পৃথক করা থ্রেড এবং রান () পদ্ধতির মধ্যে সম্ভাব্য সিঙ্ক্রোনাইজেশন সমস্যাগুলি এড়িয়ে যায়। একটি পৃথক রান্নেবল সাধারণভাবে রান্নেবল কোডটি রেফারেন্স এবং সম্পাদন করার ক্ষেত্রে আরও বেশি নমনীয়তা দেয়।


5

এটা এস এর কঠিন একক দায়িত্ব।

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

আপনি যদি একটি বাস্তবায়নে এগুলিকে একত্রে বান্ডিল করেন, আপনি ফলস্বরূপ অবজেক্টটিকে পরিবর্তনের দুটি সম্পর্কহীন কারণ দেবেন:

  1. আপনার অ্যাপ্লিকেশনে থ্রেড হ্যান্ডলিং (উদাহরণস্বরূপ অনুসন্ধান এবং প্রয়োগের প্রসঙ্গটি পরিবর্তন করা)
  2. কোড টুকরা দ্বারা চালিত অ্যালগরিদম (চলমান অংশ)

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

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

জাভা প্রসঙ্গে , যেহেতু সুবিধাটি ইতিমধ্যে রয়েছে , তাই সম্ভবত একা স্ট্যান্ড Runnableক্লাস দিয়ে সরাসরি শুরু করা এবং তাদের উদাহরণগুলি Thread(বা Executor) উদাহরণগুলিতে পাস করা সম্ভবত সহজ । এই প্যাটার্নটি একবার ব্যবহার করা হলে , সহজ রান্নেবল থ্রেড কেসের চেয়ে এটি ব্যবহার করা (বা এমনকি পড়া) বেশি কঠিন নয়।


5

আপনি বেস ক্লাসটি বাড়ানোর চেয়ে ইন্টারফেসটি প্রয়োগ করতে চান এমন একটি কারণ আপনি ইতিমধ্যে কিছু অন্যান্য শ্রেণি প্রসারিত করছেন। আপনি কেবল একটি শ্রেণি প্রসারিত করতে পারেন তবে আপনি যে কোনও সংখ্যক ইন্টারফেস প্রয়োগ করতে পারবেন।

আপনি যদি থ্রেড প্রসারিত করেন তবে আপনি মূলত 'এটি' ব্যতীত অন্য কোনও থ্রেড দ্বারা সম্পাদিত আপনার যুক্তি প্রতিরোধ করছেন। আপনি যদি কেবল নিজের যুক্তি সম্পাদন করতে কিছু থ্রেড চান তবে কেবল রান্নেবল বাস্তবায়ন করা ভাল।


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

5

আপনি যদি রান রান্নেবল ব্যবহার করেন তবে আপনার অন্য শ্রেণীর যে কোনওটিতে প্রসারিত করার জন্য স্থানটি সংরক্ষণ করতে পারেন।


5

আমরা কি আমাদের ক্লাসটিকে একটি হিসাবে আচরণ করা উচিত সেই মৌলিক কারণটি আবার দেখতে যেতে পারি? Thread ? মোটেও কোনও কারণ নেই, আমরা কেবল একটি কার্য সম্পাদন করতে চেয়েছিলাম, সম্ভবত একটি অ্যাসিনক্রোনাস মোডে, সম্ভবত এটির অর্থ হ'ল টাস্কের সম্পাদনটি অবশ্যই আমাদের মূল থ্রেড থেকে শুরু করে মূল থ্রেডটি যদি শেষ হয়ে যায় তবে অপেক্ষা করতেও পারে বা নাও হতে পারে ব্রাঞ্চযুক্ত পথ (টাস্ক) এর জন্য।

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

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

আমাদের একটি টাস্ক দরকার, সুতরাং একটি টাস্ক সংজ্ঞা লিখুন যা একটি থ্রেডে চালানো যেতে পারে। তাই রান্নেবল ব্যবহার করুন।

সর্বদা মনে রাখবেন implementsএকটি আচরণ দেওয়ার জন্য বিশেষভাবে ব্যবহৃত হয় এবং extendsএটি কোনও বৈশিষ্ট্য / সম্পত্তি সরবরাহ করতে ব্যবহৃত হয়।

আমরা থ্রেডের সম্পত্তি চাই না, পরিবর্তে আমরা চাই আমাদের ক্লাসটি এমন একটি কাজ হিসাবে আচরণ করা যা চালানো যেতে পারে।


4

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


4

আমি উল্লিখিত সমস্ত কারণে রান্নেবল ব্যবহার করা সবচেয়ে দরকারী বলে মনে করি তবে কখনও কখনও আমি থ্রেডটি প্রসারিত করতে পছন্দ করি যাতে আমি নিজের থ্রেড থামানোর পদ্ধতিটি তৈরি করতে পারি এবং এটি আমার তৈরি থ্রেডটিতে সরাসরি কল করতে পারি।


4

জাভা একাধিক উত্তরাধিকার সমর্থন করে না তাই আপনি যদি থ্রেড ক্লাস প্রসারিত করেন তবে অন্য কোনও শ্রেণি প্রসারিত হবে না।

উদাহরণস্বরূপ: আপনি যদি অ্যাপলেট তৈরি করেন তবে এটি অবশ্যই অ্যাপলেট শ্রেণিকে প্রসারিত করতে হবে সুতরাং এখানে থ্রেড তৈরির একমাত্র উপায়টি রান্নেবল ইন্টারফেস প্রয়োগ করে


4

Runnableএকটি ইন্টারফেস, অন্যদিকে Threadএমন একটি শ্রেণি যা এই ইন্টারফেসটি প্রয়োগ করে। ডিজাইনের দৃষ্টিকোণ থেকে কোনও কার্য কীভাবে সংজ্ঞায়িত করা হয় এবং কীভাবে এটি সম্পাদন করা হয় তার মধ্যে একটি পরিষ্কার বিভাজন থাকা উচিত। পূর্ববর্তীটি একটি Runnalbeবাস্তবায়নের দায়িত্ব , এবং দ্বিতীয়টি Threadশ্রেণীর কাজ। বেশিরভাগ ক্ষেত্রে বাস্তবায়ন Runnableহ'ল সঠিক উপায় অনুসরণ করা।


4

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

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


4

আমার দুটি সেন্ট এখানে যুক্ত করা - সর্বদা যখনই সম্ভব ব্যবহার হয় implements Runnable। আপনার কেন ব্যবহার করবেন না extends Threadসে সম্পর্কে নীচে দুটি সতর্কতা রয়েছে

  1. আদর্শভাবে আপনার থ্রেড ক্লাসটি কখনও বাড়ানো উচিত নয়; Threadবর্গ তৈরি করা উচিত final। কমপক্ষে এর পদ্ধতিগুলি পছন্দ করে thread.getId()। প্রসারণ সম্পর্কিত একটি বাগের জন্য এই আলোচনাটি দেখুন Thread

  2. যারা ধাঁধা সমাধান করতে চান তারা থ্রেড বাড়ানোর আরও একটি পার্শ্ব প্রতিক্রিয়া দেখতে পারেন। নীচের কোডটি অ্যাক্সেসযোগ্য কোড মুদ্রণ করবে যখন কেউ তাদেরকে অবহিত করছে না।

দয়া করে http://pastebin.com/BjKNNs2G দেখুন

public class WaitPuzzle {

    public static void main(String[] args) throws InterruptedException {
        DoNothing doNothing = new DoNothing();
        new WaitForever(doNothing).start();
        new WaitForever(doNothing).start();
        new WaitForever(doNothing).start();
        Thread.sleep(100);
        doNothing.start();
        while(true) {
            Thread.sleep(10);
        }
    }


    static class WaitForever extends  Thread {

        private DoNothing doNothing;

        public WaitForever(DoNothing doNothing) {
            this.doNothing =  doNothing;
        }

        @Override
        public void run() {
            synchronized (doNothing) {
                try {
                    doNothing.wait(); // will wait forever here as nobody notifies here
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Unreachable Code");
            }
        }
    }

    static class DoNothing extends Thread {

        @Override
        public void run() {
            System.out.println("Do Nothing ");
        }
    } 
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.