কতগুলি থ্রেড সম্পূর্ণ হওয়ার জন্য অপেক্ষা করবেন?


109

সমস্ত থ্রেড প্রক্রিয়া শেষ হওয়ার জন্য কেবল অপেক্ষা করার উপায় কী? উদাহরণস্বরূপ, আসুন আমি বলি:

public class DoSomethingInAThread implements Runnable{

    public static void main(String[] args) {
        for (int n=0; n<1000; n++) {
            Thread t = new Thread(new DoSomethingInAThread());
            t.start();
        }
        // wait for all threads' run() methods to complete before continuing
    }

    public void run() {
        // do something here
    }


}

main()সমস্ত থ্রেডের run()পদ্ধতিগুলি প্রস্থান না হওয়া পর্যন্ত পদ্ধতিটি মন্তব্যে বিরতি দেয় আমি কীভাবে এটি পরিবর্তন করব ? ধন্যবাদ!

উত্তর:


163

আপনি সমস্ত থ্রেড একটি অ্যারেতে রেখেছেন, সেগুলি শুরু করুন এবং তারপরে একটি লুপ করুন

for(i = 0; i < threads.length; i++)
  threads[i].join();

প্রতিটি থ্রেড সম্পূর্ণ না হওয়া অবধি অবরুদ্ধ হবে। থ্রেডগুলি এতে যুক্ত হওয়ার চেয়ে আলাদা ক্রমে সম্পূর্ণ হতে পারে তবে এটি কোনও সমস্যা নয়: লুপটি প্রস্থান করলে সমস্ত থ্রেড সম্পূর্ণ হয়ে যায়।


1
@ মাইকোলা: থ্রেড গ্রুপ ব্যবহার করে ঠিক কী লাভ? কেবলমাত্র
এআইপিআই থাকার কারণে

2
দেখুন: "একটি থ্রেড গ্রুপ থ্রেডের একটি সেট উপস্থাপন করে।" এটি এই ব্যবহারের ক্ষেত্রে অর্থপূর্ণ সঠিক! এবং: "একটি থ্রেডকে তার নিজস্ব থ্রেড গ্রুপ সম্পর্কে তথ্য অ্যাক্সেস করার অনুমতি দেওয়া হয়েছে"
মার্টিন কে।

4
"কার্যকর জাভা" বইটি থ্রেড গ্রুপগুলি (আইটেম 73) এড়ানো পরামর্শ দেয়।
বাসটিয়েন লোনার্ড ১৯

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

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

41

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

এক্সিকিউটর সার্ভিস এবং এর সাথে সম্পর্কিত পদ্ধতিগুলি ব্যবহার করা একটি আরও ভাল পদ্ধতির হ'ল :

List<Callable> callables = ... // assemble list of Callables here
                               // Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
//       bother saving them

একটি এক্সিকিউটার সার্ভিস (এবং জাভা 5 এর সম্মতিযুক্ত ইউটিলিটিগুলি থেকে সমস্ত নতুন স্টাফ ) ব্যবহার করা অবিশ্বাস্যরূপে নমনীয় এবং উপরের উদাহরণটি সবেমাত্র এমনকি পৃষ্ঠটিকে স্ক্র্যাচ করে।


থ্রেডগ্রুপ যাবার উপায়! পরিবর্তনীয় তালিকার সাহায্যে আপনি সমস্যায় পড়বেন (সিঙ্ক্রোনাইজেশন)
মার্টিন কে।

3
কি? কীভাবে সমস্যায় পড়বেন? এটি যে সূচনাটি চালাচ্ছে তার দ্বারা কেবল পরিবর্তনযোগ্য (কেবল পঠনযোগ্য), যতক্ষণ না এটি তালিকাটি এটির মধ্য দিয়ে পুনরাবৃত্তি করার সময় পরিবর্তন করে না , ঠিক আছে।
অ্যাডাম বাটকিন

এটি আপনি কীভাবে ব্যবহার করেন তার উপর নির্ভর করে। আপনি যদি কলিং ক্লাসটি কোনও থ্রেডে ব্যবহার করেন তবে আপনার সমস্যা হবে।
মার্টিন কে।

27
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class DoSomethingInAThread implements Runnable
{
   public static void main(String[] args) throws ExecutionException, InterruptedException
   {
      //limit the number of actual threads
      int poolSize = 10;
      ExecutorService service = Executors.newFixedThreadPool(poolSize);
      List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();

      for (int n = 0; n < 1000; n++)
      {
         Future f = service.submit(new DoSomethingInAThread());
         futures.add(f);
      }

      // wait for all tasks to complete before continuing
      for (Future<Runnable> f : futures)
      {
         f.get();
      }

      //shut down the executor service so that this thread can exit
      service.shutdownNow();
   }

   public void run()
   {
      // do something here
   }
}

মনোমুগ্ধকর মতো কাজ করেছে ... আমার কাছে দুটি সেট থ্রেড রয়েছে যা একাধিক কুকিজের কারণে সমস্যাগুলি একসাথে চালানো উচিত নয়। আমি একবারে এক ধরণের থ্রেড চালানোর জন্য আপনার উদাহরণ ব্যবহার করেছি .. আপনার জ্ঞান ভাগ করে নেওয়ার জন্য ধন্যবাদ ...
arn-arn

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

12

পরিবর্তে join(), যা একটি পুরানো এপিআই, আপনি কাউন্টডাউনল্যাচ ব্যবহার করতে পারেন । আপনার প্রয়োজনীয়তা পূরণের জন্য আমি নীচে হিসাবে আপনার কোডটি পরিবর্তন করেছি।

import java.util.concurrent.*;
class DoSomethingInAThread implements Runnable{
    CountDownLatch latch;
    public DoSomethingInAThread(CountDownLatch latch){
        this.latch = latch;
    } 
    public void run() {
        try{
            System.out.println("Do some thing");
            latch.countDown();
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

public class CountDownLatchDemo {
    public static void main(String[] args) {
        try{
            CountDownLatch latch = new CountDownLatch(1000);
            for (int n=0; n<1000; n++) {
                Thread t = new Thread(new DoSomethingInAThread(latch));
                t.start();
            }
            latch.await();
            System.out.println("In Main thread after completion of 1000 threads");
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

ব্যাখ্যা :

  1. CountDownLatch আপনার প্রয়োজন অনুযায়ী প্রদত্ত গণনা 1000 দিয়ে শুরু করা হয়েছে।

  2. প্রতিটি শ্রমিকের থ্রেড DoSomethingInAThread হ্রাস পাবে CountDownLatchযা নির্মাত্রে পাস করা হয়েছে।

  3. CountDownLatchDemo await()গণনা অবধি মূল থ্রেড শূন্য হয়ে গেছে। গণনা একবার শূন্য হয়ে গেলে আপনি আউটপুটে লাইনের নীচে পাবেন।

    In Main thread after completion of 1000 threads

ওরাকল ডকুমেন্টেশন পৃষ্ঠা থেকে আরও তথ্য

public void await()
           throws InterruptedException

থ্রেডটি বিঘ্নিত না হওয়া অবধি ল্যাচটি শূন্যতে গণনা না করা অবধি বর্তমান থ্রেডকে অপেক্ষা করতে দেয়।

অন্যান্য বিকল্পের জন্য সম্পর্কিত এসই প্রশ্নটি দেখুন:

সমস্ত থ্রেড জাভাতে তাদের কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা করুন


8

একসাথে থ্রেড ক্লাসটি এড়িয়ে চলুন এবং এর পরিবর্তে java.util.concurrent এ প্রদত্ত উচ্চতর বিমূর্তি ব্যবহার করুন

এক্সিকিউটর সার্ভিস ক্লাসটি পদ্ধতিটি আহ্বান করে যা আপনি যা চান ঠিক তেমন করে বলে মনে করে।


6

ব্যবহার বিবেচনা করুন java.util.concurrent.CountDownLatchজাভাডোকগুলিতে উদাহরণ


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

আপনার সেই উত্তরটি আপনার উত্তর শরীরে রাখা উচিত?
অ্যারন হল

জাভাডকের উদাহরণগুলি খুব বর্ণনামূলক, এজন্য আমি কোনও যোগ করি নি। docs.oracle.com/javase/7/docs/api/java/util/concurrent/… । প্রথম উদাহরণে, সমস্ত ওয়ার্কার থ্রেড একসাথে প্রকাশিত হয়েছে কারণ তারা কাউন্টডাউনল্যাচ স্টার্টসিগনালের শূন্যে পৌঁছানোর জন্য অপেক্ষা করে, যা স্টার্টসাইনাল.কাউন্টডাউন () এ ঘটে। তারপরে, মিয়ান থ্রেডটি নির্দেশকৃত সিগন্যাল.ওয়ায়েট () নির্দেশনা ব্যবহার করে সমস্ত কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা করে। সিগন্যাল প্রতিটি শ্রমিকের মধ্যে এর মান হ্রাস করে।
পাবলো ক্যাভালিরি

6

মার্টিন কে প্রস্তাবিত হিসাবে java.util.concurrent.CountDownLatchএটি এর জন্য একটি ভাল সমাধান বলে মনে হচ্ছে। একই জন্য একটি উদাহরণ যুক্ত

     public class CountDownLatchDemo
{

    public static void main (String[] args)
    {
        int noOfThreads = 5;
        // Declare the count down latch based on the number of threads you need
        // to wait on
        final CountDownLatch executionCompleted = new CountDownLatch(noOfThreads);
        for (int i = 0; i < noOfThreads; i++)
        {
            new Thread()
            {

                @Override
                public void run ()
                {

                    System.out.println("I am executed by :" + Thread.currentThread().getName());
                    try
                    {
                        // Dummy sleep
                        Thread.sleep(3000);
                        // One thread has completed its job
                        executionCompleted.countDown();
                    }
                    catch (InterruptedException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            }.start();
        }

        try
        {
            // Wait till the count down latch opens.In the given case till five
            // times countDown method is invoked
            executionCompleted.await();
            System.out.println("All over");
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }

}

4

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


3

আপনি যদি থ্রেডগুলির একটি তালিকা তৈরি করেন, আপনি সেগুলির মধ্য দিয়ে লুপ করতে পারেন এবং প্রতিটিের সাথে .join () যোগ করতে পারেন এবং সমস্ত থ্রেড থাকা অবস্থায় আপনার লুপ শেষ হবে। যদিও আমি এটি চেষ্টা করিনি।

http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#join ()


হাই, এটি কোনও কারণে আমার পক্ষে কার্যকর হয়নি। এখানে আমার প্রশ্ন: stackoverflow.com/users/5144855/ruchir-baronia
রুচির বড়োনিয়া

1

লুপের জন্য প্রথমটির ভিতরে থ্রেড অবজেক্ট তৈরি করুন।

for (int i = 0; i < threads.length; i++) {
     threads[i] = new Thread(new Runnable() {
         public void run() {
             // some code to run in parallel
         }
     });
     threads[i].start();
 }

এবং তারপরে এখানে সবাই কী বলছে।

for(i = 0; i < threads.length; i++)
  threads[i].join();

0

আপনি ঠিক কীভাবে এটি করার প্রস্তাব দিচ্ছেন তা নিশ্চিত নয়। যদি আপনি কোনও লুপটিতে অ্যাক্টিভাউন্ট পোল করার প্রস্তাব দেন: এটি খারাপ, যেহেতু এটি ব্যস্ত-অপেক্ষা (এমনকি যদি আপনি ভোটদানের মাঝে ঘুমান - তবে আপনি ব্যবসা এবং প্রতিক্রিয়াশীলতার মধ্যে একটি বাণিজ্য পেতে পারেন)।
মার্টিন বনাম লুইস

@ মার্টিন বনাম লুইস: "যোগদান কেবলমাত্র একটি একক থ্রেডের জন্য অপেক্ষা করবে A আরও ভাল সমাধান হতে পারে java.util.concurrent.CountDownLatch worker কাউন্টডাউন () এটির প্রস্থান হওয়ার ঠিক আগে, এবং মূল থ্রেডটি কেবল অপেক্ষা করায় (), যা কাউন্টার শূন্যে পৌঁছা অবধি ব্লক হয়ে যায় join একযোগে পরিবর্তন সহ। " আপনার সমাধান সমস্যার জন্য দুর্দান্ত কাজ করে তবে সাধারণ উদ্দেশ্যে নয়।
মার্টিন কে।

0

বিকল্প হিসেবে CountDownLatch আপনার কাছে ব্যবহার করতে পারেন CyclicBarrier যেমন

public class ThreadWaitEx {
    static CyclicBarrier barrier = new CyclicBarrier(100, new Runnable(){
        public void run(){
            System.out.println("clean up job after all tasks are done.");
        }
    });
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(new MyCallable(barrier));
            t.start();
        }       
    }

}    

class MyCallable implements Runnable{
    private CyclicBarrier b = null;
    public MyCallable(CyclicBarrier b){
        this.b = b;
    }
    @Override
    public void run(){
        try {
            //do something
            System.out.println(Thread.currentThread().getName()+" is waiting for barrier after completing his job.");
            b.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }       
}

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

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


আমি মনে করি না এটি সাইক্লিকবারিয়ার জন্য একটি ভাল উদাহরণ। আপনি কেন একটি থ্রেড.স্লিপ () কল ব্যবহার করেন?
গেন্টার

@ গুয়ন্তার - হ্যাঁ, আমি প্রয়োজন অনুসারে কোডটি পরিবর্তন করেছি।
শৈলেন্দ্র 1118

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

0

এটা join()আমার পক্ষে সহায়ক ছিল না। কোটলিনে এই নমুনা দেখুন:

    val timeInMillis = System.currentTimeMillis()
    ThreadUtils.startNewThread(Runnable {
        for (i in 1..5) {
            val t = Thread(Runnable {
                Thread.sleep(50)
                var a = i
                kotlin.io.println(Thread.currentThread().name + "|" + "a=$a")
                Thread.sleep(200)
                for (j in 1..5) {
                    a *= j
                    Thread.sleep(100)
                    kotlin.io.println(Thread.currentThread().name + "|" + "$a*$j=$a")
                }
                kotlin.io.println(Thread.currentThread().name + "|TaskDurationInMillis = " + (System.currentTimeMillis() - timeInMillis))
            })
            t.start()
        }
    })

ফলাফল:

Thread-5|a=5
Thread-1|a=1
Thread-3|a=3
Thread-2|a=2
Thread-4|a=4
Thread-2|2*1=2
Thread-3|3*1=3
Thread-1|1*1=1
Thread-5|5*1=5
Thread-4|4*1=4
Thread-1|2*2=2
Thread-5|10*2=10
Thread-3|6*2=6
Thread-4|8*2=8
Thread-2|4*2=4
Thread-3|18*3=18
Thread-1|6*3=6
Thread-5|30*3=30
Thread-2|12*3=12
Thread-4|24*3=24
Thread-4|96*4=96
Thread-2|48*4=48
Thread-5|120*4=120
Thread-1|24*4=24
Thread-3|72*4=72
Thread-5|600*5=600
Thread-4|480*5=480
Thread-3|360*5=360
Thread-1|120*5=120
Thread-2|240*5=240
Thread-1|TaskDurationInMillis = 765
Thread-3|TaskDurationInMillis = 765
Thread-4|TaskDurationInMillis = 765
Thread-5|TaskDurationInMillis = 765
Thread-2|TaskDurationInMillis = 765

এখন আমাকে join()থ্রেডগুলির জন্য ব্যবহার করুন :

    val timeInMillis = System.currentTimeMillis()
    ThreadUtils.startNewThread(Runnable {
        for (i in 1..5) {
            val t = Thread(Runnable {
                Thread.sleep(50)
                var a = i
                kotlin.io.println(Thread.currentThread().name + "|" + "a=$a")
                Thread.sleep(200)
                for (j in 1..5) {
                    a *= j
                    Thread.sleep(100)
                    kotlin.io.println(Thread.currentThread().name + "|" + "$a*$j=$a")
                }
                kotlin.io.println(Thread.currentThread().name + "|TaskDurationInMillis = " + (System.currentTimeMillis() - timeInMillis))
            })
            t.start()
            t.join()
        }
    })

এবং ফলাফল:

Thread-1|a=1
Thread-1|1*1=1
Thread-1|2*2=2
Thread-1|6*3=6
Thread-1|24*4=24
Thread-1|120*5=120
Thread-1|TaskDurationInMillis = 815
Thread-2|a=2
Thread-2|2*1=2
Thread-2|4*2=4
Thread-2|12*3=12
Thread-2|48*4=48
Thread-2|240*5=240
Thread-2|TaskDurationInMillis = 1568
Thread-3|a=3
Thread-3|3*1=3
Thread-3|6*2=6
Thread-3|18*3=18
Thread-3|72*4=72
Thread-3|360*5=360
Thread-3|TaskDurationInMillis = 2323
Thread-4|a=4
Thread-4|4*1=4
Thread-4|8*2=8
Thread-4|24*3=24
Thread-4|96*4=96
Thread-4|480*5=480
Thread-4|TaskDurationInMillis = 3078
Thread-5|a=5
Thread-5|5*1=5
Thread-5|10*2=10
Thread-5|30*3=30
Thread-5|120*4=120
Thread-5|600*5=600
Thread-5|TaskDurationInMillis = 3833

এটি স্পষ্ট যেমন আমরা যখন ব্যবহার করি join:

  1. থ্রেডগুলি ধারাবাহিকভাবে চলছে।
  2. প্রথম নমুনায় 765 মিলিসেকেন্ড সময় লাগে যখন দ্বিতীয় নমুনা লাগে 3833 মিলিসেকেন্ড।

অন্যান্য থ্রেডগুলি ব্লক করা রোধ করার জন্য আমাদের সমাধানটি অ্যারেলিস্ট তৈরি করছিল:

val threads = ArrayList<Thread>()

এখন যখন আমরা একটি নতুন থ্রেড শুরু করতে চাই তখন আমরা এটিকে সর্বাধিক অ্যারেলিস্টে যুক্ত করি:

addThreadToArray(
    ThreadUtils.startNewThread(Runnable {
        ...
    })
)

দ্য addThreadToArrayফাংশন:

@Synchronized
fun addThreadToArray(th: Thread) {
    threads.add(th)
}

দ্য startNewThreadfunstion:

fun startNewThread(runnable: Runnable) : Thread {
    val th = Thread(runnable)
    th.isDaemon = false
    th.priority = Thread.MAX_PRIORITY
    th.start()
    return th
}

থ্রেডগুলির যে কোনও জায়গাতে এটির প্রয়োজন হিসাবে নীচে সমাপ্তি পরীক্ষা করুন:

val notAliveThreads = ArrayList<Thread>()
for (t in threads)
    if (!t.isAlive)
        notAliveThreads.add(t)
threads.removeAll(notAliveThreads)
if (threads.size == 0){
    // The size is 0 -> there is no alive threads.
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.