কিভাবে একটি থ্রেড আউটআউট


255

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

আমি এই থ্রেডটি থেকে বের করার পরে এটি করার একটি উপায় থ্রেডের রান () পদ্ধতির অভ্যন্তরে একটি টাইমার টাস্ক ব্যবহার করা।

এর কি আরও ভাল সমাধান আছে?

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

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


সম্পাদনা: আমার আরও সুস্পষ্ট উত্তরের প্রয়োজন হিসাবে একটি অনুগ্রহ যুক্ত করা। নীচে প্রদত্ত এক্সিকিউটর সার্ভিস কোডটি আমার সমস্যার সমাধান করে না। আমার কোডটি কার্যকর করার পরে আমি কেন ঘুমাব ()? যদি কোডটি সম্পূর্ণ হয়ে যায় এবং ঘুম () ব্যাহত হয় তবে কীভাবে এটি সময়ের বাইরে যাবে?
java_geek

7
এটি sleep()"দীর্ঘকালীন চলমান কার্য" উপস্থাপনের জন্য কেবল স্টাব ছিল। কেবল এটি আপনার আসল কার্যের সাথে প্রতিস্থাপন করুন;)
BalusC

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

যদি এই উত্তরগুলি সমস্যার সমাধান না করে, তবে আমি অনুমান করি আরও বিশদ / কোডের উত্তর দিতে সহায়তা করা উচিত।
এলিস্টার

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

উত্তর:


376

এর ExecutorServiceপরিবর্তে বরং ব্যবহার করুন Timer, এখানে একটি এসএসসিসিই রয়েছে :

package com.stackoverflow.q2275443;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class Test {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new Task());

        try {
            System.out.println("Started..");
            System.out.println(future.get(3, TimeUnit.SECONDS));
            System.out.println("Finished!");
        } catch (TimeoutException e) {
            future.cancel(true);
            System.out.println("Terminated!");
        }

        executor.shutdownNow();
    }
}

class Task implements Callable<String> {
    @Override
    public String call() throws Exception {
        Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
        return "Ready!";
    }
}

পদ্ধতিতে timeoutআর্গুমেন্টের সাথে কিছুটা খেলুন Future#get(), উদাহরণস্বরূপ এটি 5 এ বাড়িয়ে দিন এবং আপনি দেখতে পাবেন যে থ্রেডটি শেষ হয়েছে। আপনি catch (TimeoutException e)ব্লকটির সময়সীমা বাধা দিতে পারেন ।

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

while (!Thread.interrupted()) {
    // Do your long running task here.
}

24
Thread.sleep(4000)কিছু অন্যান্য দীর্ঘ-চলমান বিবৃতি দিয়ে প্রতিস্থাপন করুন এবং উদাহরণটি কাজ করবে না। অন্য কথায়, এই উদাহরণটি কেবল তখনই কাজ করবে যদি স্থিতি পরিবর্তন Taskবোঝার জন্য ডিজাইন করা হয় Thread.isInterrupted()
yegor256

@ বালুসসি আমি আমার থ্রেডগুলি বন্ধ করার চেষ্টা করে এই পদ্ধতির চেষ্টা করেছি, কিন্তু এটি কার্যকর করতে পারেনি। : আপনি এটি এখানে পরীক্ষা করতে পারবেন stackoverflow.com/questions/35553420/...
syfantid

কীভাবে বিঘ্নিত ধারণা গ্রহণ করা যায় ভবিষ্যতের ক্যানসেল (সত্য) দ্বারা পরিচালিত?
বোলেই

1
n জনসংখ্যক লোক প্যাকেজটির নাম সম্পর্কে মন্তব্য করেছে এবং এর জন্য আরও একটি +1 এখানে রয়েছে। বিস্মৃত হওয়ার মতো এমন দুর্দান্ত দক্ষতা। ধন্যবাদ!
আশ্বিন তুম্মা

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

49

কোনও পুরানো কাজের জন্য এটি করার জন্য 100% নির্ভরযোগ্য উপায় নেই। এই ক্ষমতাটি মাথায় রেখে কাজটি লিখতে হবে।

কোর জাভা গ্রন্থাগারগুলি কর্মী থ্রেডে কল ExecutorServiceসহ অ্যাসিক্রোনাস টাস্কগুলি বাতিল করা পছন্দ interrupt()করে। সুতরাং, উদাহরণস্বরূপ, যদি কার্যটিতে কোনও ধরণের লুপ থাকে তবে আপনার প্রতিটি পুনরাবৃত্তির উপর এর বিঘ্নিত অবস্থানটি পরীক্ষা করা উচিত । যদি টাস্কটি I / O ক্রিয়াকলাপগুলি করে চলেছে তবে সেগুলিও খুব বাধা হওয়া উচিত — এবং এটি নির্ধারণ করা জটিল be যে কোনও ক্ষেত্রে, মনে রাখবেন যে কোডটিকে সক্রিয়ভাবে বাধা রোধ করতে হবে; বাধা নির্ধারণ করা অগত্যা কিছু করে না।

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


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

@ থরবজর্নআরভানএন্ডারসেন আমি সম্মত, কিন্তু এটি অনেক কোড। আমার বক্তব্যটি হ'ল এর পক্ষে কোনও সাধারণ-উদ্দেশ্যমূলক ব্যবস্থা নেই; আপনাকে কাজের বিঘ্নিত নীতি বুঝতে হবে।
এরিকসন

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

ক্যান্ট এক্সিকিউটরস সার্ভিস কলিং থ্রেডে টাস্কটি চালাতে চান? এছাড়াও এক্সিকিউটার্স সার্ভিস ভবিষ্যতে কোনও সময় টাস্কটি কার্যকর করতে পছন্দ করতে পারে?
ফিলিটি_উইজার্ড

@ ব্যবহারকারী 1232726 execute()পিতামাতার ইন্টারফেসের পদ্ধতি,Executor কলিং থ্রেডে কোনও কাজ চালাতে পারে। এই রিটার্ন উদাহরণগুলির submit()পদ্ধতির জন্য কোনও অনুরূপ বিবৃতি নেই । পরিষেবাটির নিদর্শনটি হ'ল এখানে কর্মী থ্রেডগুলি রয়েছে যা শাটডাউনের মাধ্যমে পরিষ্কার করতে হবে এবং সেই কাজগুলি অযৌক্তিকভাবে সম্পাদন করা হয়। এটি বলেছিল, চুক্তিতে এমন কিছুই নেই যা বলে যে জমা দেওয়ার থ্রেডে কার্য সম্পাদন করা নিষিদ্ধ; এই গ্যারান্টিগুলি কারখানাগুলির মতো বাস্তবায়নকারী API থেকে আসে । ExecutorServiceFutureExecutorServiceExecutors
ইরিকসন

13

এক্সিকিউটর সার্ভিসের একটি উদাহরণ ব্যবহার করে বিবেচনা করুন । উভয় invokeAll()এবং invokeAny()পদ্ধতি একটি timeoutপরামিতি সঙ্গে উপলব্ধ ।

প্রক্রিয়াটি সম্পূর্ণ না হওয়া অবধি বর্তমান থ্রেডটি ব্লক হয়ে যাবে (কোনও বিষয়টি পছন্দসই কিনা তা নিশ্চিত নয়) হয় কারণ টাস্ক (গুলি) সাধারণত সম্পন্ন হয় বা সময়সীমা অতিক্রম করে। Futureকী ঘটেছে তা নির্ধারণ করতে আপনি ফিরে (গুলি) পরিদর্শন করতে পারেন ।


9

থ্রেড কোড ধরে নেওয়া আপনার নিয়ন্ত্রণের বাইরে চলে গেছে:

উপরে বর্ণিত জাভা ডকুমেন্টেশন থেকে :

কোনও থ্রেড থ্রেড.ইনটার্টে সাড়া না দিলে কী হবে?

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

শেষের সারি:

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


8

বালুসসি বলেছেন:

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

তবে আপনি যদি এর Thread.sleep(4000);সাথে প্রতিস্থাপন করেন for (int i = 0; i < 5E8; i++) {}তবে এটি সংকলন করে না, কারণ খালি লুপটি একটি নিক্ষেপ করে না InterruptedException

এবং থ্রেডটি বাধাপ্রাপ্ত হওয়ার জন্য, এটি একটি নিক্ষেপ করা প্রয়োজন InterruptedException

এটি আমার কাছে একটি গুরুতর সমস্যা বলে মনে হচ্ছে। একটি দীর্ঘ দীর্ঘস্থায়ী কাজ করে কীভাবে এই উত্তরটি মানিয়ে নেবে তা আমি দেখতে পাচ্ছি না।

যোগ করার জন্য সম্পাদিত: আমি এটি একটি নতুন প্রশ্ন হিসাবে পুনরায় জিজ্ঞাসা করেছি: [ নির্দিষ্ট সময় পরে একটি থ্রেড বাধাগ্রস্ত করা, এটির জন্য বাধা কী? ]


আমি যেভাবে করি তা হ'ল জনসাধারণের ক্লাস <T> কল করুন call} পদ্ধতিতে একটি ´থ্রো ব্যতিক্রম যুক্ত করা
রবার্তো

5

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

আপনি যেটি বর্ণনা করছেন, এটি খুব খুব "একটি উপস্থাপক " এর মতো শোনায় , তাই আপনি সাইক্লিক বেরিয়ারটি একবার দেখে নিতে পারেন ।

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

: আমি সাধারণত এই এলাকায় দুটি বই সুপারিশ জাভা কংকারেন্ট প্রোগ্রামিং এবং প্র্যাকটিস জাভা concurrency


5

কিছু সময়ের আগে আমি এর জন্য একটি সহায়ক শ্রেণি তৈরি করেছি। দুর্দান্ত কাজ করে:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
 * TimeOut class - used for stopping a thread that is taking too long
 * @author Peter Goransson
 *
 */
public class TimeOut {

    Thread interrupter;
    Thread target;
    long timeout;
    boolean success;
    boolean forceStop;

    CyclicBarrier barrier;

    /**
     * 
     * @param target The Runnable target to be executed
     * @param timeout The time in milliseconds before target will be interrupted or stopped
     * @param forceStop If true, will Thread.stop() this target instead of just interrupt() 
     */
    public TimeOut(Runnable target, long timeout, boolean forceStop) {      
        this.timeout = timeout;
        this.forceStop = forceStop;

        this.target = new Thread(target);       
        this.interrupter = new Thread(new Interrupter());

        barrier = new CyclicBarrier(2); // There will always be just 2 threads waiting on this barrier
    }

    public boolean execute() throws InterruptedException {  

        // Start target and interrupter
        target.start();
        interrupter.start();

        // Wait for target to finish or be interrupted by interrupter
        target.join();  

        interrupter.interrupt(); // stop the interrupter    
        try {
            barrier.await(); // Need to wait on this barrier to make sure status is set
        } catch (BrokenBarrierException e) {
            // Something horrible happened, assume we failed
            success = false;
        } 

        return success; // status is set in the Interrupter inner class
    }

    private class Interrupter implements Runnable {

        Interrupter() {}

        public void run() {
            try {
                Thread.sleep(timeout); // Wait for timeout period and then kill this target
                if (forceStop) {
                  target.stop(); // Need to use stop instead of interrupt since we're trying to kill this thread
                }
                else {
                    target.interrupt(); // Gracefully interrupt the waiting thread
                }
                System.out.println("done");             
                success = false;
            } catch (InterruptedException e) {
                success = true;
            }


            try {
                barrier.await(); // Need to wait on this barrier
            } catch (InterruptedException e) {
                // If the Child and Interrupter finish at the exact same millisecond we'll get here
                // In this weird case assume it failed
                success = false;                
            } 
            catch (BrokenBarrierException e) {
                // Something horrible happened, assume we failed
                success = false;
            }

        }

    }
}

এটিকে এভাবে বলা হয়:

long timeout = 10000; // number of milliseconds before timeout
TimeOut t = new TimeOut(new PhotoProcessor(filePath, params), timeout, true);
try {                       
  boolean sucess = t.execute(); // Will return false if this times out
  if (!sucess) {
    // This thread timed out
  }
  else {
    // This thread ran completely and did not timeout
  }
} catch (InterruptedException e) {}  

3

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

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


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * Main class
 * 
 * @author el
 * 
 */
public class Main {
    /**
     * Thread which perform the task which should be timed out.
     * 
     * @author el
     * 
     */
    public static class MainThread extends Thread {
        /**
         * For example reading a file. File to read.
         */
        final private File fileToRead;
        /**
         * InputStream from the file.
         */
        final private InputStream myInputStream;
        /**
         * Thread for timeout.
         */
        final private TimeOutThread timeOutThread;

        /**
         * true if the thread has not ended.
         */
        boolean isRunning = true;

        /**
         * true if all tasks where done.
         */
        boolean everythingDone = false;

        /**
         * if every thing could not be done, an {@link Exception} may have
         * Happens.
         */
        Throwable endedWithException = null;

        /**
         * Constructor.
         * 
         * @param file
         * @throws FileNotFoundException
         */
        MainThread(File file) throws FileNotFoundException {
            setDaemon(false);
            fileToRead = file;
            // open the file stream.
            myInputStream = new FileInputStream(fileToRead);
            // Instantiate the timeout thread.
            timeOutThread = new TimeOutThread(10000, this);
        }

        /**
         * Used by the {@link TimeOutThread}.
         */
        public void kill() {
            if (isRunning) {
                isRunning = false;
                if (myInputStream != null) {
                    try {
                        // close the stream, it may be the problem.
                        myInputStream.close();
                    } catch (IOException e) {
                        // Not interesting
                        System.out.println(e.toString());
                    }
                }
                synchronized (this) {
                    notify();
                }
            }
        }

        /**
         * The task which should be timed out.
         */
        @Override
        public void run() {
            timeOutThread.start();
            int bytes = 0;
            try {
                // do something
                while (myInputStream.read() >= 0) {
                    // may block the thread.
                    myInputStream.read();
                    bytes++;
                    // simulate a slow stream.
                    synchronized (this) {
                        wait(10);
                    }
                }
                everythingDone = true;
            } catch (IOException e) {
                endedWithException = e;
            } catch (InterruptedException e) {
                endedWithException = e;
            } finally {
                timeOutThread.kill();
                System.out.println("-->read " + bytes + " bytes.");
                isRunning = false;
                synchronized (this) {
                    notifyAll();
                }
            }
        }
    }

    /**
     * Timeout Thread. Kill the main task if necessary.
     * 
     * @author el
     * 
     */
    public static class TimeOutThread extends Thread {
        final long timeout;
        final MainThread controlledObj;

        TimeOutThread(long timeout, MainThread controlledObj) {
            setDaemon(true);
            this.timeout = timeout;
            this.controlledObj = controlledObj;
        }

        boolean isRunning = true;

        /**
         * If we done need the {@link TimeOutThread} thread, we may kill it.
         */
        public void kill() {
            isRunning = false;
            synchronized (this) {
                notify();
            }
        }

        /**
         * 
         */
        @Override
        public void run() {
            long deltaT = 0l;
            try {
                long start = System.currentTimeMillis();
                while (isRunning && deltaT < timeout) {
                    synchronized (this) {
                        wait(Math.max(100, timeout - deltaT));
                    }
                    deltaT = System.currentTimeMillis() - start;
                }
            } catch (InterruptedException e) {
                // If the thread is interrupted,
                // you may not want to kill the main thread,
                // but probably yes.
            } finally {
                isRunning = false;
            }
            controlledObj.kill();
        }
    }

    /**
     * Start the main task and wait for the end.
     * 
     * @param args
     * @throws FileNotFoundException
     */
    public static void main(String[] args) throws FileNotFoundException {
        long start = System.currentTimeMillis();
        MainThread main = new MainThread(new File(args[0]));
        main.start();
        try {
            while (main.isRunning) {
                synchronized (main) {
                    main.wait(1000);
                }
            }
            long stop = System.currentTimeMillis();

            if (main.everythingDone)
                System.out.println("all done in " + (stop - start) + " ms.");
            else {
                System.out.println("could not do everything in "
                        + (stop - start) + " ms.");
                if (main.endedWithException != null)
                    main.endedWithException.printStackTrace();
            }
        } catch (InterruptedException e) {
            System.out.println("You've killed me!");
        }
    }
}

শুভেচ্ছা সহ


3

জাভা কোডের টুকরো চালাতে বা কল করতে সহায়ক সহায়ক ক্লাসটি ব্যবহার করা আমার এখানে খুব সহজ :-)

এই চমৎকার উপর ভিত্তি করে তৈরি উত্তর থেকে BalusC

package com.mycompany.util.concurrent;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Calling {@link Callable#call()} or Running {@link Runnable#run()} code
 * with a timeout based on {@link Future#get(long, TimeUnit))}
 * @author pascaldalfarra
 *
 */
public class CallableHelper
{

    private CallableHelper()
    {
    }

    public static final void run(final Runnable runnable, int timeoutInSeconds)
    {
        run(runnable, null, timeoutInSeconds);
    }

    public static final void run(final Runnable runnable, Runnable timeoutCallback, int timeoutInSeconds)
    {
        call(new Callable<Void>()
        {
            @Override
            public Void call() throws Exception
            {
                runnable.run();
                return null;
            }
        }, timeoutCallback, timeoutInSeconds); 
    }

    public static final <T> T call(final Callable<T> callable, int timeoutInSeconds)
    {
        return call(callable, null, timeoutInSeconds); 
    }

    public static final <T> T call(final Callable<T> callable, Runnable timeoutCallback, int timeoutInSeconds)
    {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        try
        {
            Future<T> future = executor.submit(callable);
            T result = future.get(timeoutInSeconds, TimeUnit.SECONDS);
            System.out.println("CallableHelper - Finished!");
            return result;
        }
        catch (TimeoutException e)
        {
            System.out.println("CallableHelper - TimeoutException!");
            if(timeoutCallback != null)
            {
                timeoutCallback.run();
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        catch (ExecutionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            executor.shutdownNow();
            executor = null;
        }

        return null;
    }

}

2

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

ExecutorService executorService = getExecutorService();
Future<SomeClass> future = executorService.submit(new Callable<SomeClass>() {
    public SomeClass call() {
        // Perform long-running task, return result. The code should check
        // interrupt status regularly, to facilitate cancellation.
    }
});
try {
    // Real life code should define the timeout as a constant or
    // retrieve it from configuration
    SomeClass result = future.get(10, TimeUnit.SECONDS);
    // Do something with the result
} catch (TimeoutException e) {
    future.cancel(true);
    // Perform other error handling, e.g. logging, throwing an exception
}

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


প্রয়োজনীয় আমদানিগুলি কী কী? কি SomeClassএবং Future?
এডিটিসি

2

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

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


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

@ আলেসান্দ্রোস: এটি একটি যুক্তিসঙ্গত বিষয়, যদিও ওপি "আরও ভাল সমাধান" চেয়েছিল, যার দ্বারা আমি বোঝাতে চেয়েছি যে দৃru়তা এবং নির্ভরযোগ্যতা বর্বর শক্তির চেয়ে বেশি পছন্দ করা হয়েছিল।
ড্যান পুজে

2

বালাসসির দুর্দান্ত উত্তর:

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

package com.stackoverflow.q2275443; 

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;


public class Test { 
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new Task());

        try { 
            System.out.println("Started..");
            System.out.println(future.get(3, TimeUnit.SECONDS));
            System.out.println("Finished!");
        } catch (TimeoutException e) {
            //Without the below cancel the thread will continue to live 
            // even though the timeout exception thrown.
            future.cancel();
            System.out.println("Terminated!");
        } 

        executor.shutdownNow();
    } 
} 

class Task implements Callable<String> {
    @Override 
    public String call() throws Exception {
      while(!Thread.currentThread.isInterrupted()){
          System.out.println("Im still running baby!!");
      }          
    } 
} 

0

আমি মনে করি উত্তরটি মূলত নিজের উপর নির্ভর করে।

  • এটি বার বার একটি কাজ করছে?
  • এটি কি প্রয়োজনীয় যে সময়সীমাটি কোনও চলমান কার্যের মেয়াদ শেষ হওয়ার সাথে সাথেই বাধা দেয়?

যদি প্রথম উত্তরটি হ্যাঁ হয় এবং দ্বিতীয়টি না হয় তবে আপনি এটি এতটা সহজ রাখতে পারেন:

public class Main {

    private static final class TimeoutTask extends Thread {
        private final long _timeoutMs;
        private Runnable _runnable;

        private TimeoutTask(long timeoutMs, Runnable runnable) {
            _timeoutMs = timeoutMs;
            _runnable = runnable;
        }

        @Override
        public void run() {
            long start = System.currentTimeMillis();
            while (System.currentTimeMillis() < (start + _timeoutMs)) {
                _runnable.run();
            }
            System.out.println("execution took " + (System.currentTimeMillis() - start) +" ms");
        }

    }

    public static void main(String[] args) throws Exception {
        new TimeoutTask(2000L, new Runnable() {

            @Override
            public void run() {
                System.out.println("doing something ...");
                try {
                    // pretend it's taking somewhat longer than it really does
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }
}

যদি এটি কোনও বিকল্প না হয় তবে দয়া করে আপনার প্রয়োজনীয়তাগুলি সংকীর্ণ করুন - বা কিছু কোড দেখান।


0

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

public class TimedExecutorService extends ThreadPoolExecutor {
    long timeout;
    public TimedExecutorService(int numThreads, long timeout, TimeUnit unit) {
        super(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(numThreads + 1));
        this.timeout = unit.toMillis(timeout);
    }

    @Override
    protected void beforeExecute(Thread thread, Runnable runnable) {
        Thread interruptionThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // Wait until timeout and interrupt this thread
                    Thread.sleep(timeout);
                    System.out.println("The runnable times out.");
                    thread.interrupt();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        interruptionThread.start();
    }
}

ব্যবহার:

public static void main(String[] args) {

    Runnable abcdRunnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("abcdRunnable started");
            try {
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                // logger.info("The runnable times out.");
            }
            System.out.println("abcdRunnable ended");
        }
    };

    Runnable xyzwRunnable = new Runnable() {
        @Override
        public void run() {
            System.out.println("xyzwRunnable started");
            try {
                Thread.sleep(20000);
            } catch (InterruptedException e) {
                // logger.info("The runnable times out.");
            }
            System.out.println("xyzwRunnable ended");
        }
    };

    int numThreads = 2, timeout = 5;
    ExecutorService timedExecutor = new TimedExecutorService(numThreads, timeout, TimeUnit.SECONDS);
    timedExecutor.execute(abcdRunnable);
    timedExecutor.execute(xyzwRunnable);
    timedExecutor.shutdown();
}

0

এখন, আমি এই জাতীয় একটি সমস্যা পূরণ। এটি ছবির ডিকোড করতে ঘটে। ডিকোড প্রক্রিয়াটি স্ক্রিনটি কালো রাখার জন্য অনেক বেশি সময় নেয়। আমি একটি সময় নিয়ন্ত্রক যুক্ত করব: যখন সময়টি খুব দীর্ঘ হয়, তারপরে বর্তমান থ্রেড থেকে পপআপ করুন। নিম্নলিখিতটি পৃথক:

   ExecutorService executor = Executors.newSingleThreadExecutor();
   Future<Bitmap> future = executor.submit(new Callable<Bitmap>() {
       @Override
       public Bitmap call() throws Exception {
       Bitmap bitmap = decodeAndScaleBitmapFromStream(context, inputUri);// do some time consuming operation
       return null;
            }
       });
       try {
           Bitmap result = future.get(1, TimeUnit.SECONDS);
       } catch (TimeoutException e){
           future.cancel(true);
       }
       executor.shutdown();
       return (bitmap!= null);

0

আমারও একই সমস্যা ছিল। সুতরাং আমি এই মত একটি সহজ সমাধান নিয়ে এসেছি।

public class TimeoutBlock {

 private final long timeoutMilliSeconds;
    private long timeoutInteval=100;

    public TimeoutBlock(long timeoutMilliSeconds){
        this.timeoutMilliSeconds=timeoutMilliSeconds;
    }

    public void addBlock(Runnable runnable) throws Throwable{
        long collectIntervals=0;
        Thread timeoutWorker=new Thread(runnable);
        timeoutWorker.start();
        do{ 
            if(collectIntervals>=this.timeoutMilliSeconds){
                timeoutWorker.stop();
                throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
            }
            collectIntervals+=timeoutInteval;           
            Thread.sleep(timeoutInteval);

        }while(timeoutWorker.isAlive());
        System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
    }

    /**
     * @return the timeoutInteval
     */
    public long getTimeoutInteval() {
        return timeoutInteval;
    }

    /**
     * @param timeoutInteval the timeoutInteval to set
     */
    public void setTimeoutInteval(long timeoutInteval) {
        this.timeoutInteval = timeoutInteval;
    }
}

গ্যারান্টি দেয় যে ব্লক যদি সময়সীমার মধ্যে কার্যকর না করে। প্রক্রিয়াটি সমাপ্ত হবে এবং একটি ব্যতিক্রম ছোঁড়াবে।

উদাহরণ:

try {
        TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
        Runnable block=new Runnable() {

            @Override
            public void run() {
                //TO DO write block of code 
            }
        };

        timeoutBlock.addBlock(block);// execute the runnable block 

    } catch (Throwable e) {
        //catch the exception here . Which is block didn't execute within the time limit
    }

0

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

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

জেনেরিক ক্লাসটি নীচের মতো প্রয়োগ করা উচিত:

import java.util.List;
import java.util.concurrent.*;

public class TimeoutThreadPoolDecorator extends ThreadPoolExecutor {


    private final ThreadPoolExecutor commandThreadpool;
    private final long timeout;
    private final TimeUnit unit;

    public TimeoutThreadPoolDecorator(ThreadPoolExecutor threadpool,
                                      long timeout,
                                      TimeUnit unit ){
        super(  threadpool.getCorePoolSize(),
                threadpool.getMaximumPoolSize(),
                threadpool.getKeepAliveTime(TimeUnit.MILLISECONDS),
                TimeUnit.MILLISECONDS,
                threadpool.getQueue());

        this.commandThreadpool = threadpool;
        this.timeout=timeout;
        this.unit=unit;
    }

    @Override
    public void execute(Runnable command) {
        super.execute(() -> {
            Future<?> future = commandThreadpool.submit(command);
            try {
                future.get(timeout, unit);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } catch (ExecutionException | TimeoutException e) {
                throw new RejectedExecutionException(e);
            } finally {
                future.cancel(true);
            }
        });
    }

    @Override
    public void setCorePoolSize(int corePoolSize) {
        super.setCorePoolSize(corePoolSize);
        commandThreadpool.setCorePoolSize(corePoolSize);
    }

    @Override
    public void setThreadFactory(ThreadFactory threadFactory) {
        super.setThreadFactory(threadFactory);
        commandThreadpool.setThreadFactory(threadFactory);
    }

    @Override
    public void setMaximumPoolSize(int maximumPoolSize) {
        super.setMaximumPoolSize(maximumPoolSize);
        commandThreadpool.setMaximumPoolSize(maximumPoolSize);
    }

    @Override
    public void setKeepAliveTime(long time, TimeUnit unit) {
        super.setKeepAliveTime(time, unit);
        commandThreadpool.setKeepAliveTime(time, unit);
    }

    @Override
    public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
        super.setRejectedExecutionHandler(handler);
        commandThreadpool.setRejectedExecutionHandler(handler);
    }

    @Override
    public List<Runnable> shutdownNow() {
        List<Runnable> taskList = super.shutdownNow();
        taskList.addAll(commandThreadpool.shutdownNow());
        return taskList;
    }

    @Override
    public void shutdown() {
        super.shutdown();
        commandThreadpool.shutdown();
    }
}

উপরের সাজসজ্জারটি নীচের হিসাবে ব্যবহার করা যেতে পারে:

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Main {

    public static void main(String[] args){

        long timeout = 2000;

        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<>(true));

        threadPool = new TimeoutThreadPoolDecorator( threadPool ,
                timeout,
                TimeUnit.MILLISECONDS);


        threadPool.execute(command(1000));
        threadPool.execute(command(1500));
        threadPool.execute(command(2100));
        threadPool.execute(command(2001));

        while(threadPool.getActiveCount()>0);
        threadPool.shutdown();


    }

    private static Runnable command(int i) {

        return () -> {
            System.out.println("Running Thread:"+Thread.currentThread().getName());
            System.out.println("Starting command with sleep:"+i);
            try {
                Thread.sleep(i);
            } catch (InterruptedException e) {
                System.out.println("Thread "+Thread.currentThread().getName()+" with sleep of "+i+" is Interrupted!!!");
                return;
            }
            System.out.println("Completing Thread "+Thread.currentThread().getName()+" after sleep of "+i);
        };

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