একই থ্রেডে দু'বার শুরুর পদ্ধতিটি কল করা কি আইনী?


90

নিম্নলিখিত কোড বিশালাকার java.lang.IllegalThreadStateException: Thread already startedআমি ডাকলে start()পদ্ধতি দ্বিতীয় সময় প্রোগ্রামে।

updateUI.join();    

if (!updateUI.isAlive()) 
    updateUI.start();

এই ঘটনা দ্বিতীয় সময় updateUI.start()বলা হয়। আমি একাধিকবার এটি পেরিয়েছি এবং থ্রেডটি কল করা হয়েছে এবং আঘাতের আগে সম্পূর্ণরূপে চলে updateUI.start()

কলিং updateUI.run()ত্রুটি এড়ায় কিন্তু থ্রেডটি ইউআই থ্রেডে চালিত করে (কলিং থ্রেড, যেমন এসও-র অন্যান্য পোস্টে উল্লিখিত), যা আমি চাই না।

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


9
আপনি কেবলমাত্র জাভাডোকটি পড়েন নি কেন - এটি স্পষ্টতই চুক্তির বর্ণনা দেয়।
এমপি।

উত্তর:


112

থেকে জাভা এপিআই স্পেসিফিকেশন জন্য Thread.startপদ্ধতি:

থ্রেড একবারে শুরু করা বৈধ নয়। বিশেষত, কোনও থ্রেড কার্যকর হওয়ার পরে পুনরায় আরম্ভ করা হবে না।

আরও:

নিক্ষেপ:
IllegalThreadStateException- থ্রেডটি ইতিমধ্যে শুরু করা থাকলে।

হ্যাঁ, একটি Threadকেবল একবার শুরু করা যেতে পারে।

যদি তাই হয় তবে আমি আবার থ্রেডটি চালাতে চাইলে আমি কী করব?

যদি Threadএকাধিকবার চালানোর প্রয়োজন হয় তবে তার একটি নতুন ইভেন্ট তৈরি করা উচিত Threadএবং startএটিতে কল করা উচিত।


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

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

এটি আবর্জনা সংগ্রহ করা হবে, যতক্ষণ না থ্রেড আর চলবে না।
ফ্লাইওয়েং

4
এই উত্তরটি কিছুটা পুরানো। যদি কোনও আধুনিক জাভা প্রোগ্রামটি একাধিকবার কোনও কার্য সম্পাদন করার প্রয়োজন হয় , তবে এটি Threadপ্রতিবার নতুন তৈরি করা উচিত নয় । পরিবর্তে, এটি কোনও থ্রেড পুলে (যেমন, java.util.concurrent.ThreadPoolExecutor) জমা দেওয়া উচিত
সলোমন স্লো

13

একদম ঠিক. ডকুমেন্টেশন থেকে :

থ্রেড একবারে শুরু করা বৈধ নয়। বিশেষত, কোনও থ্রেড কার্যকর হওয়ার পরে পুনরায় আরম্ভ করা হবে না।

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

এখানে ডকুমেন্টেশন থেকে উদাহরণ:

 Runnable doHelloWorld = new Runnable() {
     public void run() {
         // Put your UI update computations in here.
         // BTW - remember to restrict Swing calls to the AWT Event thread.
         System.out.println("Hello World on " + Thread.currentThread());
     }
 };

 SwingUtilities.invokeLater(doHelloWorld);
 System.out.println("This might well be displayed before the other message.");

যদি আপনি সেই printlnকলটিকে আপনার গণনার সাথে প্রতিস্থাপন করেন তবে এটি আপনার প্রয়োজন ঠিক ঠিক হতে পারে।

সম্পাদনা: মন্তব্য অনুসরণ করে, আমি মূল পোস্টে অ্যান্ড্রয়েড ট্যাগটি লক্ষ্য করিনি। অ্যান্ড্রয়েড কাজের ইনভোকলটারের সমতুল্য Handler.post(Runnable)। এর জাভাডোক থেকে:

/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is
 * attached.
 *
 * @param r The Runnable that will be executed.
 *
 * @return Returns true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 */

সুতরাং, অ্যান্ড্রয়েড বিশ্বে আপনি উপরের মতো একই উদাহরণ ব্যবহার করতে পারেন, Swingutilities.invokeLaterযথাযথ পোস্টটি এটিকে প্রতিস্থাপন করে Handler


ওপি অ্যান্ড্রয়েডে থ্রেডিংয়ের বিষয়ে জিজ্ঞাসা করছে, যার মধ্যে সুইং ইউটিলিটিস অন্তর্ভুক্ত নেই।
অস্টিন মাহুনি

@ অস্টিন, আপনি ঠিক বলেছেন। আমি সমান্তরাল অ্যান্ড্রয়েড কোডটি চিত্রিত করতে Handler.post () সম্পর্কে মন্তব্যগুলি যুক্ত করেছি।
বব ক্রস

4
আরেকটি উপায় আপনি শুধু আপনার ইউআই আপডেট করার চেষ্টা করছেন ব্যবহার করা RunOnUIThread(Runnable)বা View.post(Runnable)আপনার নিজের হ্যান্ডলার তৈরি করার পরিবর্তে। এটি আপনাকে ইউআই আপডেট করার অনুমতি দিয়ে মূল থ্রেডে চলবে।
অস্টিন মাহুনি

3

সদ্য-আগত উত্তরে আপনাকে কী করা উচিত তা কেন করা উচিত তা কভার করে না। আপনার প্রকৃত সমস্যা সমাধানের জন্য এখানে কিছু বিকল্প রয়েছে।

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

আপনার নিজের থ্রেড ডাম্প এবং ব্যবহার করুন AsyncTask

বা আপনার যখন প্রয়োজন তখন একটি নতুন থ্রেড তৈরি করুন।

অথবা থ্রেডটি LinkedBlockingQueueপুনরায় আরম্ভ করার চেয়ে কোনও ওয়ার্ক সারি (উদাঃ ) ব্যবহার করে আপনার থ্রেড সেট আপ করুন ।


3

না , আমরা আবার থ্রেড শুরু করতে পারি না, এটি করলে রানটাইম এক্সেক্সপশন জাভা.এল.এনএলআইগ্যালথ্রথডস্টেটএক্সসেপশন নিক্ষেপ হবে। >

কারণটি একবার চালানো হয় () পদ্ধতিটি থ্রেড দ্বারা কার্যকর করা হয়, এটি মৃত অবস্থায় চলে যায়।

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

public class MyClass implements Runnable{

    @Override
    public void run() {
           System.out.println("in run() method, method completed.");
    }

    public static void main(String[] args) {
                  MyClass obj=new MyClass();            
        Thread thread1=new Thread(obj,"Thread-1");
        thread1.start();
        thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
    }

}

/ * রান () পদ্ধতিতে OUTPUT, পদ্ধতি সম্পূর্ণ। থ্রেড "মেইন" java.lang.IllegalThreadStateException এ java.lang.Thread.start এ অজানা (অজানা উত্স) * /

এটা যাচাই কর


2

আপনার যা করা উচিত তা হ'ল রান্নেবল তৈরি করা এবং রান্নেবল চালানোর সময় প্রতিবার নতুন থ্রেডের সাথে এটি মোড়ানো। এটি করা সত্যই কুৎসিত হবে তবে আপনি কোডটি আবার চালানোর জন্য অন্য থ্রেডের সাথে একটি থ্রেড মোড়ানো করতে পারেন তবে কেবল এটিই করতে পারেন যা আপনাকে সত্যিই করতে হবে।


কোন স্নিপেট, কীভাবে মোড়ানো?
বিনয়

1

এটি যেমনটি আপনি বলেছেন, একটি থ্রেড একাধিকবার শুরু করা যায় না।

সরাসরি ঘোড়ার মুখ থেকে: জাভা এপিআই স্পেক

থ্রেড একবারে শুরু করা বৈধ নয়। বিশেষত, কোনও থ্রেড কার্যকর হওয়ার পরে পুনরায় আরম্ভ করা হবে না।

আপনার থ্রেডে যা চলছে তা যদি আবার চালানোর দরকার হয় তবে আপনাকে একটি নতুন থ্রেড তৈরি করতে হবে এবং এটি চালাতে হবে।


0

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


0

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

আপনার যদি সত্যিই থ্রেড শুরু করতে হবে: বিকল্প 1) যদি কোনও থ্রেডটি একাধিকবার চালানোর প্রয়োজন হয়, তবে থ্রেডের একটি নতুন উদাহরণ তৈরি করা উচিত এবং তার উপর কল কল শুরু করা উচিত।


0

একটি থ্রেড একবারে শুরু করা যেতে পারে?

হ্যাঁ. আপনি ঠিক একবার এটি শুরু করতে পারেন।

যদি আমি থ্রেডটি আবার চালাতে চাই তবে আমি কী করব? এই নির্দিষ্ট থ্রেডটি ব্যাকগ্রাউন্ডে কিছু গণনা করছে, যদি আমি থ্রিতে এটি না করি তবে এটি ইউআই থ্রেডে করা হয়েছে এবং ব্যবহারকারীর কাছে অযৌক্তিকভাবে দীর্ঘ অপেক্ষা.

Threadআবার চালাবেন না । এর পরিবর্তে তৈরি runnable এবং এর তা পোস্ট হ্যান্ডলার এর HandlerThread । আপনি একাধিক Runnableবস্তু জমা দিতে পারেন । আপনার Runnable run()পদ্ধতিটি সহ, যদি ইউআই থ্রেডে ডেটা ফেরত পাঠাতে চান , তবে ইউআই থ্রেড এবং প্রক্রিয়াটির একটি পোস্ট MessageকরুনHandlerhandleMessage

উদাহরণস্বরূপ কোডের জন্য এই পোস্টটি দেখুন:

অ্যান্ড্রয়েড: একটি থ্রেড টোস্ট


0

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

আমি জানি এটি আবার কোনও সূতা শুরু করছে না, তবে এটি আপনার পক্ষে কার্যকর হবে।

public void run() {

    LifeCycleComponent lifeCycleComponent = new LifeCycleComponent();

    try {
        NetworkState firstState = lifeCycleComponent.getCurrentNetworkState();
        Thread.sleep(5000);
        if (firstState != lifeCycleComponent.getCurrentNetworkState()) {
            System.out.println("{There was a NetworkState change!}");
            run();
        } else {
            run();
        }
    } catch (SocketException | InterruptedException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {
    Thread checkingNetworkStates = new Thread(new LifeCycleComponent());
    checkingNetworkStates.start();
}

আশা করি এটি সামান্য হলেও সামান্য হলেও সহায়তা করে।

চিয়ার্স


-1

এটি করা সত্যই কুৎসিত হবে তবে আপনি কোডটি আবার চালানোর জন্য অন্য থ্রেডের সাথে একটি থ্রেড মোড়ানো করতে পারেন তবে কেবল এটিই করতে পারেন যা আপনাকে সত্যিই করতে হবে।

আমাকে এমন একটি রিসোর্স লিক ঠিক করতে হয়েছিল যা একটি প্রোগ্রামার দ্বারা সৃষ্ট থ্রেড তৈরি করেছিল তবে এটি শুরু করার পরিবর্তে, তিনি রান () - পদ্ধতিটিকে সরাসরি বলেছেন। সুতরাং এটিকে এড়িয়ে চলুন, যদি না আপনি সত্যিই জানেন যে এটি কী কী প্রতিক্রিয়া সৃষ্টি করে know


তবে পরামর্শটি run()সরাসরি কল করার জন্য নয় , কেবল একটি থ্রেডে একটি রান্নেবল এম্বেড করার জন্য এবং সম্ভবত অনুরোধ জানানো হয়েছিল start()
H2ONaCl

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