একটি পরামিতি দিয়ে চলমান?


178

আমার একটি "রাননেবল যা একটি প্যারামিটার গ্রহণ করে" এর দরকার আছে যদিও আমি জানি যে এ জাতীয় চলমান সত্যিকার অর্থেই বিদ্যমান নেই।

এটা আমার অ্যাপ্লিকেশন এবং / অথবা আমার ক্লান্ত মস্তিষ্কে একটি মানসিক ব্লক নকশা মৌলিক ত্রুটি নির্দেশ করতে পারে, তাই আমি এখানে কিভাবে নিচের মত কিছু সম্পন্ন করার জন্য কিছু পরামর্শ এটি আশা করছি ছাড়া মৌলিক OO যেমন পণ্য নীতিগুলো লঙ্ঘন:

  private Runnable mOneShotTask = new Runnable(String str) {
    public void run(String str) {
       someFunc(str);
    }
  };  

উপরের মতো কিছু কীভাবে সম্পাদন করবেন কোনও ধারণা?


7
এখন আপনি ব্যবহার করতে পারেন Consumer<T>
অ্যালেক্স 78191

1
আমি এই প্রশ্নের বিভিন্ন উত্তর পড়েছি। এটিকে আমার কাছে অদ্ভুত বলে মনে হচ্ছে যে কেউ আপনার প্রজেক্টে আপনার যে রান্নেবলগুলি প্রয়োজন তা যুক্ত করতে পারেন (এক, দুই, তিন বা ততোধিক অর্গ সহ) কেবল একটি উপযুক্ত ইন্টারফেস যুক্ত করতে পারেন। কারা আগ্রহী সে জন্য আমি এখানে একটি মন্তব্য সংক্ষিপ্তসার তৈরি করেছি: gist.github.com/jsfan3/3a66e711fd0fd233c5e4c467184adb7a
ফ্রান্সেসকো গালগানি

এটি "জাভা থ্রেডে আমি কীভাবে প্যারামিটারটি পাস করতে পারি" এর সদৃশ নয়। এবং আধুনিক উত্তরটি হ'ল @ অ্যালেক্স 78191 বলেছেন: ব্যবহার করুনConsumer<T>
এপাগা

উত্তর:


228

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

void foo(final String str) {
    Thread t = new Thread(() -> someFunc(str));
    t.start();
}

আগের মতোই, সেই থ্রেডকে অর্থবহ উপায়ে পরিচালনা করার মতো বিশদ বিবরণ পাঠকের কাছে অনুশীলন হিসাবে রেখে দেওয়া হয়েছে। তবে কথায় কথায় বলতে গেলে, যদি আপনি ল্যাম্বডাস ব্যবহার করতে ভয় পান তবে আপনাকে মাল্টি-থ্রেডেড সিস্টেমগুলির থেকে আরও ভয় পাওয়া উচিত।

আসল উত্তর, ঠিক কারণ:

আপনি পদ্ধতিটিতে ডানদিকে ক্লাস ঘোষণা করতে পারেন

void Foo(String str) {
    class OneShotTask implements Runnable {
        String str;
        OneShotTask(String s) { str = s; }
        public void run() {
            someFunc(str);
        }
    }
    Thread t = new Thread(new OneShotTask(str));
    t.start();
}

সবাইকে ধন্যবাদ! প্রস্তাবিত সমস্ত সমাধান একই পদ্ধতির দিকে ইঙ্গিত করে তবে আমি কেবল একটি গ্রহণ করতে পারি। আমি নিজেই এটিকে সামনে আসতে না পেরে আমাকে খুব ক্লান্ত হতে হবে। সবার কাছে +1।
uTubeFan

18
আসলে, বেশিরভাগ লোকেরা জানেন না আপনি কোনও পদ্ধতির অভ্যন্তরে কোনও শ্রেণি ঘোষণা করতে পারেন। কেউ কেউ এটিকে দুর্বল শৈলী হিসাবে বিবেচনা করবেন। আমার ধারণা এটি স্বাদের বিষয়। :)
কর্সিকা

3
পাবলিক ইন্টারফেস রেজাল্টচালিত <T> {সর্বজনীন শূন্য রানের (টি ফলাফল); }
রোমান এম

46

আপনি এটি একটি ফাংশন রাখতে পারেন।

String paramStr = "a parameter";
Runnable myRunnable = createRunnable(paramStr);

private Runnable createRunnable(final String paramStr){

    Runnable aRunnable = new Runnable(){
        public void run(){
            someFunc(paramStr);
        }
    };

    return aRunnable;

}

(আমি যখন এটি ব্যবহার করেছি, আমার প্যারামিটারটি একটি পূর্ণসংখ্যার আইডি ছিল, যা আমি আইডি -> মাইআরনেবলসমূহের হ্যাশম্যাপ তৈরি করতাম way এইভাবে, আমি হ্যান্ডলারে বিভিন্ন আমারআরনেবল অবজেক্টগুলি পোস্ট / সরাতে হ্যাশম্যাপটি ব্যবহার করতে পারি))


3
কোডটি ভাগ করে নেওয়ার জন্য ধন্যবাদ - আমি পছন্দ করি যখন লোকেরা কেবল বকবক করার পরিবর্তে এটি করে। একটি প্রশ্ন - মেমরি ফাঁস করার বিষয়টি কি উপরে রয়েছে? আপনার পাস করা সমস্ত রেফারেন্সগুলি সঠিকভাবে নিষ্পত্তি হবে?
নিকিব 3ro

2
@ কেপে 123 উত্তরটি "এটি নির্ভর করে"। যতক্ষণ Runnableনা পদ্ধতিতে ফিরে আসা কোনও বস্তু কোথাও উপস্থিত থাকে ততক্ষণ paramStrসম্ভবত আবর্জনা সংগ্রহের জন্য যোগ্য হবে না। এটা সম্ভব যে যদি বস্তুটি বিদ্যমান থাকে তবে আবার কখনও চালানো না যায়, জেআইটি (বা এমনকি জাভাক) এটিকে সুযোগ থেকে সরিয়ে নেওয়ার সিদ্ধান্ত নিতে পারে, তবে আমাদের যেমন অপ্টিমাইজেশানের উপর নির্ভর করা উচিত নয় কারণ ভবিষ্যতে তারা পরিবর্তিত হতে পারে।
corsiKa

"কোডটি ভাগ করে নেওয়ার জন্য ধন্যবাদ - আমি পছন্দ করি যখন লোকেরা কেবল বকবক করার পরিবর্তে এটি করে।" - কি?
রব গ্রান্ট

30
theView.post(new Runnable() {
    String str;
    @Override                            
    public void run() {
        par.Log(str);                              
    }
    public Runnable init(String pstr) {
        this.str=pstr;
        return(this);
    }
}.init(str));

Init ফাংশন তৈরি করুন যা স্বয়ং বস্তুটি ফেরত দেয় এবং এটির সাথে পরামিতিগুলি সূচনা করে।


1
দুর্ভাগ্যক্রমে আপনি এটিকে কোনও ভেরিয়েবলের কাছে বরাদ্দ করতে এবং
থিম

11

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

public abstract class RunnableArg implements Runnable {

    Object[] m_args;

    public RunnableArg() {
    }

    public void run(Object... args) {
        setArgs(args);
        run();
    }

    public void setArgs(Object... args) {
        m_args = args;
    }

    public int getArgCount() {
        return m_args == null ? 0 : m_args.length;
    }

    public Object[] getArgs() {
        return m_args;
    }
}

2
প্যারামিটার দিয়ে রান রানযোগ্য চালাতে আপনি এই বিমূর্ত ক্লাসটি কীভাবে ব্যবহার করবেন?
EZDsIt

আমি প্যারামিটারগুলির সাথে কনস্ট্রাক্টর ব্যবহার করতে পছন্দ করি public RunnableArg(Object... args) { setArgs(args); } তারপরে স্থানীয় শ্রেণি বর্ণনা: class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } } এবং এটি ব্যবহার করুন Thread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
জিএসডি.আজ

10

আপনার দুটি বিকল্প রয়েছে:

  1. একটি নামী বর্গ নির্ধারণ করুন। আপনার প্যারামিটারটি নামী বর্গের কনস্ট্রাক্টরে পাস করুন।

  2. আপনার বেনামে ক্লাসটি আপনার "প্যারামিটার" এর কাছাকাছি রাখুন। এটি হিসাবে চিহ্নিত করতে ভুলবেন না final



6

জাভা 8 থেকে, সর্বোত্তম উত্তরটি ব্যবহার করা Consumer<T>:

https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html

এটি কার্যকরী ইন্টারফেসগুলির মধ্যে একটি, যার অর্থ আপনি এটিকে ল্যাম্বডা এক্সপ্রেশন হিসাবে কল করতে পারেন:

void doSomething(Consumer<String> something) {
    something.accept("hello!");
}

...

doSomething( (something) -> System.out.println(something) )

...

5

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

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