কোনও থ্রেড থেকে কীভাবে একটি ব্যতিক্রম ধরা যায়


165

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

কোডটি এখানে:

public class Test extends Thread
{
  public static void main(String[] args) throws InterruptedException
  {
    Test t = new Test();

    try
    {
      t.start();
      t.join();
    }
    catch(RuntimeException e)
    {
      System.out.println("** RuntimeException from main");
    }

    System.out.println("Main stoped");
  }

  @Override
  public void run()
  {
    try
    {
      while(true)
      {
        System.out.println("** Started");

        sleep(2000);

        throw new RuntimeException("exception from thread");
      }
    }
    catch (RuntimeException e)
    {
      System.out.println("** RuntimeException from thread");

      throw e;
    } 
    catch (InterruptedException e)
    {

    }
  }
}

কেউ জানে কেন?

উত্তর:


220

ব্যবহার ক Thread.UncaughtExceptionHandler

Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread th, Throwable ex) {
        System.out.println("Uncaught exception: " + ex);
    }
};
Thread t = new Thread() {
    @Override
    public void run() {
        System.out.println("Sleeping ...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted.");
        }
        System.out.println("Throwing exception ...");
        throw new RuntimeException();
    }
};
t.setUncaughtExceptionHandler(h);
t.start();

13
আমি কি করতে পারি, যদি আমি একটি উচ্চ স্তরের ব্যতিক্রমটি ফেলে দিতে চাই?
রোদি

6
@ রডী একটি অস্থির পরিবর্তনশীলটিতে প্রাক্তন সংরক্ষণ করুন যা উপরের স্তরটি হ্যান্ডলারে দেখতে পারে (যেমন সদস্য ভেরিয়েবল)। বাইরে, নাল কিনা তা পরীক্ষা করুন, অন্যথায় নিক্ষেপ করুন। অথবা একটি নতুন অস্থির ক্ষেত্রের সাথে ইউইএইচ প্রসারিত করুন এবং ব্যতিক্রম সেখানে সংরক্ষণ করুন।
সিরো সান্তিলি :0 冠状 病 六四 事件 法轮功

1
আমি আমার থ্রেডের ভিতরে থেকে একটি ব্যতিক্রম ধরতে চাই - এটি বন্ধ না করেই। এটি কি কোনও উপকারে আসবে?
লেওলো

42

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

আপনি যদি এই অবিচ্ছিন্ন ব্যতিক্রম সম্পর্কে সচেতন হতে চান তবে আপনি এটি চেষ্টা করতে পারেন:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("Caught " + e);
    }
});

অপ্রয়োজনীয় ব্যতিক্রম পরিচালনা সম্পর্কে আরও তথ্য এখানে পাওয়া যাবে


আমি যে পছন্দ! স্থির পদ্ধতিতে হ্যান্ডলারটি সেট করা Thread.setDefaultUncaughtExceptionHandler()থ্রেড "মেইন" ব্যতিক্রমগুলিও ধরা দেয়
টিও জে

38

এটি কোনও ব্যতিক্রম ঘটেছে কি না তার উপর নির্ভরশীল থ্রেডগুলির রাজ্য স্থানান্তর ব্যাখ্যা করে:

থ্রেড এবং ব্যতিক্রম হ্যান্ডলিং

সূত্র: http://www-public.imtbs-tsp.eu/~gibson/ টিচিং / সিএসসি 7322/ L8- এক্সেক্সসেশনএন্ড থ্রেডস.পিডিএফ


12
আপনি কি চিত্রটি তৈরি করেছেন? যদি না হয় তবে উত্সটি কী?
ফ্লো

23

সম্ভবত;

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

যাইহোক, ধরে নেওয়া যাক আপনাকে চাইল্ড থ্রেড থেকে অন্য কোনও ব্যতিক্রম পরিচালনা করতে হবে। আমি এইরকম একটি এক্সিকিউটার সার্ভিস ব্যবহার করব:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new Callable<Void>() {
    @Override
    public Void call() throws Exception {
        System.out.println("** Started");
        Thread.sleep(2000);
        throw new IllegalStateException("exception from thread");
    }
});
try {
    future.get(); // raises ExecutionException for any uncaught exception in child
} catch (ExecutionException e) {
    System.out.println("** RuntimeException from thread ");
    e.getCause().printStackTrace(System.out);
}
executor.shutdown();
System.out.println("** Main stopped");

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

** Started
** RuntimeException from thread 
java.lang.IllegalStateException: exception from thread
    at Main$1.call(Main.java:11)
    at Main$1.call(Main.java:6)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
** Main stopped

তবে future.get()থ্রেডটির সম্পাদনা শেষ না হওয়া পর্যন্ত অপেক্ষা বা অবরুদ্ধ করে না ?
গ্রেগর ভ্যালেন্টিন

থ্রেড চলমান / কলযোগ্যতা শেষ না হওয়া পর্যন্ত @ গ্রেগরভ্যালেনটিন এটি অপেক্ষা / অবরুদ্ধ করে।
পিটার লরে


3

Callableথ্রেডের পরিবর্তে ব্যবহার করুন , তারপরে আপনি কল করতে পারবেন Future#get()যা কলযোগ্য ছুঁড়ে ফেলেছে এমন কোনও ব্যতিক্রম ছুঁড়ে ফেলবে।


1
মনে রাখবেন যে ভিতরে ফেলে দেওয়া ব্যতিক্রমটি একটিতে Callable.callমুড়ে গেছে ExcecutionExceptionএবং এর কারণটি মূল্যায়ন করতে হবে।
কার্ল রিখটার

3

বর্তমানে আপনি কেবল ধরছেন RuntimeException, এর একটি সাব ক্লাস Exception। তবে আপনার অ্যাপ্লিকেশনটি ব্যতিক্রমের অন্যান্য উপ-শ্রেণি ফেলতে পারে । জেনেরিক Exceptionছাড়াও ধরুনRuntimeException

থ্রেডিং ফ্রন্টে যেহেতু অনেকগুলি জিনিস পরিবর্তন করা হয়েছে, তাই অ্যাডভান্স জাভা এপিআই ব্যবহার করুন।

বা এর মতো মাল্টি-থ্রেডিংয়ের জন্য অগ্রিম java.util.concurrent API পছন্দ করুন ।ExecutorServiceThreadPoolExecutor

ব্যতিক্রমগুলি পরিচালনা করতে আপনি আপনার থ্রেডপুলএক্সিকিউটরকে কাস্টমাইজ করতে পারেন ।

ওরাকল ডকুমেন্টেশন পৃষ্ঠা থেকে উদাহরণ:

অগ্রাহ্য করা

protected void afterExecute(Runnable r,
                            Throwable t)

প্রদত্ত রান্নেবলের কার্য সম্পাদন শেষে পদ্ধতিটি অনুরোধ করা হয়েছিল। এই পদ্ধতিটি থ্রেড দ্বারা চালিত হয়েছিল যা কার্য সম্পাদন করে। অ-শূন্য হলে, থ্রোয়েবল হ'ল অপ্রচলিত রানটাইম এক্সসেপশন বা ত্রুটি যা ফলশ্রুতি হঠাৎ করে বন্ধ করে দেয়।

উদাহরণ কোড:

class ExtendedExecutor extends ThreadPoolExecutor {
   // ...
   protected void afterExecute(Runnable r, Throwable t) {
     super.afterExecute(r, t);
     if (t == null && r instanceof Future<?>) {
       try {
         Object result = ((Future<?>) r).get();
       } catch (CancellationException ce) {
           t = ce;
       } catch (ExecutionException ee) {
           t = ee.getCause();
       } catch (InterruptedException ie) {
           Thread.currentThread().interrupt(); // ignore/reset
       }
     }
     if (t != null)
       System.out.println(t);
   }
 }

ব্যবহার:

ExtendedExecutor service = new ExtendedExecutor();

আমি উপরের কোডের উপরে একটি কনস্ট্রাক্টর যুক্ত করেছি:

 public ExtendedExecutor() { 
       super(1,5,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
   }

আপনি থ্রেড সংখ্যার উপর আপনার প্রয়োজন অনুসারে এই নির্মাতা পরিবর্তন করতে পারেন।

ExtendedExecutor service = new ExtendedExecutor();
service.submit(<your Callable or Runnable implementation>);

2

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

class TestClass implements Runnable{
    private Exception ex;

        @Override
        public void run() {
            try{
                //business code
               }catch(Exception e){
                   ex=e;
               }
          }

      public void checkForException() throws Exception {
            if (ex!= null) {
                throw ex;
            }
        }
}     

যোগদানের পরে চেকফোরএক্সেপশন () কে কল করুন ()


1

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

আপনি সেখানে আপনার সমস্যার উত্তর খুঁজে পেতে পারেন ... শুভকামনা! :-)


1

এছাড়াও জাভা 8 থেকে আপনি ড্যান ক্রুজ এর উত্তর লিখতে পারেন:

Thread t = new Thread(()->{
            System.out.println("Sleeping ...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Interrupted.");
            }
            System.out.println("Throwing exception ...");
            throw new RuntimeException(); });


t.setUncaughtExceptionHandler((th, ex)-> log(String.format("Exception in thread %d id: %s", th.getId(), ex)));
t.start();

1

এটমিক রেফারেন্স ত্রুটিটি মূল থ্রেডে পাস করার সমাধানও solutionকেন একই পদ্ধতির মতো ড্যান ক্রুজ।

AtomicReference<Throwable> errorReference = new AtomicReference<>();

    Thread thread = new Thread() {
        public void run() {
            throw new RuntimeException("TEST EXCEPTION");

        }
    };
    thread.setUncaughtExceptionHandler((th, ex) -> {
        errorReference.set(ex);
    });
    thread.start();
    thread.join();
    Throwable newThreadError= errorReference.get();
    if (newThreadError!= null) {
        throw newThreadError;
    }  

একমাত্র পরিবর্তনটি হ'ল একটি অস্থির পরিবর্তনশীল তৈরির পরিবর্তে আপনি AtomicReferences ব্যবহার করতে পারেন যা পর্দার আড়ালে একই কাজ করেছিল।


0

এটি প্রসারিত করা প্রায় সর্বদা ভুল Thread। আমি এটিকে দৃ strongly়ভাবে বলতে পারি না।

মাল্টিথ্রেডিং বিধি # 1: প্রসারিত Threadকরা ভুল *

Runnableপরিবর্তে যদি আপনি বাস্তবায়ন করেন তবে আপনি আপনার প্রত্যাশিত আচরণ দেখতে পাবেন।

public class Test implements Runnable {

  public static void main(String[] args) {
    Test t = new Test();
    try {
      new Thread(t).start();
    } catch (RuntimeException e) {
      System.out.println("** RuntimeException from main");
    }

    System.out.println("Main stoped");

  }

  @Override
  public void run() {
    try {
      while (true) {
        System.out.println("** Started");

        Thread.sleep(2000);

        throw new RuntimeException("exception from thread");
      }
    } catch (RuntimeException e) {
      System.out.println("** RuntimeException from thread");
      throw e;
    } catch (InterruptedException e) {

    }
  }
}

উত্পাদন করে;

Main stoped
** Started
** RuntimeException from threadException in thread "Thread-0" java.lang.RuntimeException: exception from thread
    at Test.run(Test.java:23)
    at java.lang.Thread.run(Thread.java:619)

* যদি না আপনি আপনার অ্যাপ্লিকেশনটি থ্রেডগুলি ব্যবহার করার পদ্ধতিটি পরিবর্তন করতে চান তবে এটি 99.9% ক্ষেত্রে না। আপনি যদি মনে করেন যে আপনি 0.1% ক্ষেত্রে আছেন তবে দয়া করে নিয়ম # 1 দেখুন।


7
এটি মূল পদ্ধতিতে ব্যতিক্রমটি ধরা দেয় না।
ফিলাবিব

থ্রেড শ্রেণীর প্রসারিত করা দৃ strongly়ভাবে নিরুৎসাহিত। আমি এটি এবং ব্যাখ্যাটি কেন ওজেপিসি প্রস্তুতিতে পড়ি। বই ... অনুমান করুন, তারা জানে তারা কী সম্পর্কে কথা বলছে
luigi7up

2
"মূল থেকে রানটাইমএক্সেপশন" কখনই এখানে মুদ্রিত হয় না .. ব্যতিক্রমটি মূলভাবে ধরা পড়ে না
আম্রিশ পান্ডে

0

আপনি যদি থ্রেডটি প্রয়োগ করেন। থ্রেডগুলি শুরু করে এমন ক্লাসে অনাকাঙ্ক্ষিত হ্যান্ডলার, আপনি সেট করতে পারেন এবং তারপরে ব্যতিক্রমটি পুনর্বিবেচনা করতে পারেন:

public final class ThreadStarter implements Thread.UncaughtExceptionHandler{

private volatile Throwable initException;

    public void doSomeInit(){
        Thread t = new Thread(){
            @Override
            public void run() {
              throw new RuntimeException("UNCAUGHT");
            }
        };
        t.setUncaughtExceptionHandler(this);

        t.start();
        t.join();

        if (initException != null){
            throw new RuntimeException(initException);
        }

    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        initException =  e;
    }    

}

যা নিম্নলিখিত ফলাফলের কারণ:

Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: UNCAUGHT
    at com.gs.gss.ccsp.enrichments.ThreadStarter.doSomeInit(ThreadStarter.java:24)
    at com.gs.gss.ccsp.enrichments.ThreadStarter.main(ThreadStarter.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.RuntimeException: UNCAUGHT
    at com.gs.gss.ccsp.enrichments.ThreadStarter$1.run(ThreadStarter.java:15)

T.join () সিঙ্ক্রোনাইজ হবে সেহেতু থ্রোয়েবল ডিগ্রিএক্সেপশনকে অস্থির করতে হবে না।
নিকল

0

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

যদি আমরা অপ্রকাশিত এক্সসেপশনহ্যান্ডলার সেট না করি তবে থ্রেডস থ্রেডগ্রুপ একটি হ্যান্ডলার হিসাবে কাজ করে।

 public class FirstThread extends Thread {

int count = 0;

@Override
public void run() {
    while (true) {
        System.out.println("FirstThread doing something urgent, count : "
                + (count++));
        throw new RuntimeException();
    }

}

public static void main(String[] args) {
    FirstThread t1 = new FirstThread();
    t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        public void uncaughtException(Thread t, Throwable e) {
            System.out.printf("Exception thrown by %s with id : %d",
                    t.getName(), t.getId());
            System.out.println("\n"+e.getClass());
        }
    });
    t1.start();
}
}

Http://coder2design.com/thread-creation/#exception এ চমৎকার ব্যাখ্যা দেওয়া হয়েছে


0

আরএক্সজাবার সাথে আমার সমাধান:

@Test(expectedExceptions = TestException.class)
public void testGetNonexistentEntry() throws Exception
{
    // using this to work around the limitation where the errors in onError (in subscribe method)
    // cannot be thrown out to the main thread
    AtomicReference<Exception> ex = new AtomicReference<>();
    URI id = getRandomUri();
    canonicalMedia.setId(id);

    client.get(id.toString())
        .subscribe(
            m ->
                fail("Should not be successful"),
            e ->
                ex.set(new TestException()));

    for(int i = 0; i < 5; ++i)
    {
        if(ex.get() != null)
            throw ex.get();
        else
            Thread.sleep(1000);
    }
    Assert.fail("Cannot find the exception to throw.");
}

0

যারা প্রয়োজনের জন্য সব টপিক চলমান থামাতে এবং তাদের সব পুনরায় চালানোর যখন তাদের কাউকে এক একটি ব্যতিক্রম এসে বসত হয়:

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {

     // could be any function
     getStockHistory();

}


public void getStockHistory() {

     // fill a list of symbol to be scrapped
     List<String> symbolListNYSE = stockEntityRepository
     .findByExchangeShortNameOnlySymbol(ContextRefreshExecutor.NYSE);


    storeSymbolList(symbolListNYSE, ContextRefreshExecutor.NYSE);

}


private void storeSymbolList(List<String> symbolList, String exchange) {

    int total = symbolList.size();

    // I create a list of Thread 
    List<Thread> listThread = new ArrayList<Thread>();

    // For each 1000 element of my scrapping ticker list I create a new Thread
    for (int i = 0; i <= total; i += 1000) {
        int l = i;

        Thread t1 = new Thread() {

            public void run() {

                // just a service that store in DB my ticker list
                storingService.getAndStoreStockPrice(symbolList, l, 1000, 
                MULTIPLE_STOCK_FILL, exchange);

            }

        };

    Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread thread, Throwable exception) {

                // stop thread if still running
                thread.interrupt();

                // go over every thread running and stop every one of them
                listThread.stream().forEach(tread -> tread.interrupt());

                // relaunch all the Thread via the main function
                getStockHistory();
            }
        };

        t1.start();
        t1.setUncaughtExceptionHandler(h);

        listThread.add(t1);

    }

}

সংক্ষেপে:

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


-5

আপনি এটি করতে পারবেন না, যেহেতু এটি সত্যিকার অর্থে বোঝায় না। যদি আপনি কল না করেন t.join()তবে tথ্রেডটি ব্যতিক্রম ছুঁড়ে মারলে আপনার মূল থ্রেড কোডের যে কোনও জায়গায় থাকতে পারে ।

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