কেউ কী আমাকে পরামর্শ দিতে পারে যে আমি কীভাবে একটি থ্রেডে প্যারামিটারটি পাস করতে পারি?
এছাড়াও, এটি বেনাম শ্রেণীর জন্য কীভাবে কাজ করে?
Consumer<T>
।
কেউ কী আমাকে পরামর্শ দিতে পারে যে আমি কীভাবে একটি থ্রেডে প্যারামিটারটি পাস করতে পারি?
এছাড়াও, এটি বেনাম শ্রেণীর জন্য কীভাবে কাজ করে?
Consumer<T>
।
উত্তর:
আপনাকে রান্টেবল অবজেক্টে কনস্ট্রাক্টরের প্যারামিটারটি পাস করতে হবে:
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
এবং এইভাবে প্রার্থনা করুন:
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
r
একই আর্গুমেন্ট থাকবে, সুতরাং আমরা যদি একাধিক থ্রেডে চলমান বিভিন্ন আর্গুমেন্টটি পাস MyThread
করতে চাই তবে MyThread
প্রতিটি থ্রেডের জন্য কাঙ্ক্ষিত যুক্তি ব্যবহার করে আমাদের একটি নতুন উদাহরণ তৈরি করা দরকার create অন্য কথায়, একটি থ্রেড আপ এবং চলমান পেতে আমাদের দুটি বস্তু তৈরি করতে হবে: থ্রেড এবং মাই থ্রেড। এটাকে কী খারাপ, কর্মক্ষমতা অনুযায়ী বিবেচনা করা হবে?
প্রশ্ন সম্পাদনার প্রতিক্রিয়া হিসাবে এখানে এটি বেনাম শ্রেণীর জন্য কীভাবে কাজ করে
final X parameter = ...; // the final is important
Thread t = new Thread(new Runnable() {
p = parameter;
public void run() {
...
};
t.start();
আপনার কাছে এমন একটি শ্রেণি রয়েছে যা থ্রেড (বা চালিতযোগ্য প্রয়োগ করে) এবং আপনি যে প্যারামিটারগুলি দিয়ে যেতে চান তা নির্ধারণকারী। তারপরে, আপনি যখন নতুন থ্রেডটি তৈরি করবেন তখন আপনাকে আর্গুমেন্টে পাস করতে হবে এবং তার পরে থ্রেডটি শুরু করতে হবে:
Thread t = new MyThread(args...);
t.start();
থ্রেড বিটিডাব্লুয়ের চেয়ে রান্নেবল একটি আরও ভাল সমাধান। সুতরাং আমি পছন্দ করব:
public class MyRunnable implements Runnable {
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void run() {
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
এই উত্তরটি মূলত এই অনুরূপ প্রশ্নের মতোই: কোনও থ্রেড অবজেক্টে পরামিতি কীভাবে পাস করতে হয়
parameter
থেকে সরাসরি অ্যাক্সেস করি । মনে হচ্ছে এটি কাজ করে। আগে থেকে অনুলিপি না করে আমি কি কিছু সূক্ষ্ম মাল্টিথ্রেডিং জিনিস মিস করছি ? run()
p
parameter
p
)
প্রথম উদাহরণটিতে একটি মিস করছেন
final X parameter
না new Runnable()
লাইনের আগে আমার কাছে ছিল তখন আমি parameter
ভিতরে প্রবেশ করতে পারতাম run()
। আমার অতিরিক্ত করার দরকার পড়েনি p = parameter
।
final
এটি আর গুরুত্বপূর্ণ নয়; পরিবর্তনশীল কার্যকরভাবে চূড়ান্ত হলে এটি যথেষ্ট (যদিও এটির কোনও ক্ষতি না হলেও)
একটি চলমান বা থ্রেড শ্রেণীর নির্মাণকারীর মাধ্যমে
class MyThread extends Thread {
private String to;
public MyThread(String to) {
this.to = to;
}
@Override
public void run() {
System.out.println("hello " + to);
}
}
public static void main(String[] args) {
new MyThread("world!").start();
}
@Override
?
@Override
স্পষ্টতই বলা হয়েছে যে এটি থ্রেড ক্লাসে বিমূর্ত পদ্ধতিটি ওভাররাইড করছে।
এই উত্তরটি খুব দেরিতে আসে তবে সম্ভবত কেউ এটির কাজে লাগবে। Runnable
নামযুক্ত শ্রেণি (ইনলাইনারদের পক্ষে কার্যকর) ঘোষণা না করে কীভাবে কোনও পরামিতি (গুলি) পাস করার বিষয়ে এটি:
String someValue = "Just a demo, really...";
new Thread(new Runnable() {
private String myParam;
public Runnable init(String myParam) {
this.myParam = myParam;
return this;
}
@Override
public void run() {
System.out.println("This is called from another thread.");
System.out.println(this.myParam);
}
}.init(someValue)).start();
অবশ্যই আপনি কার্যকর start
করা কিছু আরও সুবিধাজনক বা উপযুক্ত মুহুর্তে স্থগিত করতে পারেন । এবং init
পদ্ধতির স্বাক্ষর কী হবে তা আপনার উপর নির্ভর করে (সুতরাং এটি আরও এবং / অথবা বিভিন্ন যুক্তি লাগতে পারে) এবং অবশ্যই এর নামও, তবে মূলত আপনি একটি ধারণা পাবেন get
প্রকৃতপক্ষে ব্লক ব্যবহার করে বেনাম শ্রেণিতে একটি প্যারামিটার পাশ করার আরও একটি উপায় রয়েছে। এই বিবেচনা:
String someValue = "Another demo, no serious thing...";
int anotherValue = 42;
new Thread(new Runnable() {
private String myParam;
private int myOtherParam;
{
this.myParam = someValue;
this.myOtherParam = anotherValue;
}
@Override
public void run() {
System.out.println("This comes from another thread.");
System.out.println(this.myParam + ", " + this.myOtherParam);
}
}).start();
সুতরাং সব ইনিশিয়ালার ব্লকের ভিতরে ঘটে।
this.myParam
আসলেই কি প্রয়োজনীয়? আপনি কি কেবল প্রাইভেট ভেরিয়েবলগুলি বাদ দিতে এবং বহিরাগত সুযোগ থেকে ভেরিয়েবলটি উল্লেখ করতে পারবেন না? আমি বুঝতে পারি (অবশ্যই) এর কিছু জড়িত রয়েছে যেমন থ্রেড শুরু করার পরে পরিবর্তনশীলটি পরিবর্তনের জন্য উন্মুক্ত।
আপনি যখন একটি থ্রেড তৈরি করেন, আপনার একটি দৃষ্টান্ত প্রয়োজন Runnable
। প্যারামিটারে যাওয়ার সহজতম উপায় হ'ল এটি নির্মাণকারীর পক্ষে যুক্তি হিসাবে পাস করা:
public class MyRunnable implements Runnable {
private volatile String myParam;
public MyRunnable(String myParam){
this.myParam = myParam;
...
}
public void run(){
// do something with myParam here
...
}
}
MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();
আপনি যদি থ্রেড চলমান অবস্থায় প্যারামিটারটি পরিবর্তন করতে চান তবে আপনি কেবল আপনার রানযোগ্য ক্লাসে একটি সেটার পদ্ধতি যুক্ত করতে পারেন:
public void setMyParam(String value){
this.myParam = value;
}
একবার আপনার এটি হয়ে গেলে আপনি এই জাতীয় কল করে প্যারামিটারটির মান পরিবর্তন করতে পারেন:
myRunnable.setMyParam("Goodbye World");
অবশ্যই, যদি আপনি প্যারামিটারটি পরিবর্তন করা হয় তখন কোনও ক্রিয়া ট্রিগার করতে চান, আপনাকে লকগুলি ব্যবহার করতে হবে, যা জিনিসগুলিকে যথেষ্ট জটিল করে তোলে।
একটি থ্রেড তৈরি করতে আপনি সাধারণত রান্নেবলের নিজস্ব বাস্তবায়ন তৈরি করেন। এই শ্রেণীর নির্মাত্রে থ্রেডে পরামিতিগুলি পাস করুন।
class MyThread implements Runnable{
private int a;
private String b;
private double c;
public MyThread(int a, String b, double c){
this.a = a;
this.b = b;
this.c = c;
}
public void run(){
doSomething(a, b, c);
}
}
আপনি হয় বা প্রসারিত করতে পারেন এবং আপনি চান হিসাবে পরামিতি সরবরাহ করতে পারেন। দস্তাবেজগুলিতে সহজ উদাহরণ রয়েছে । আমি তাদের এখানে পোর্ট করব:Thread
class
Runnable
class
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
হয় এমন একটি ক্লাস লিখুন যা রান্নেবলকে কার্যকর করে, এবং যথাযথ সংজ্ঞায়িত কনস্ট্রাক্টারে আপনার যা কিছু প্রয়োজন তা পাস করুন, বা এমন একটি ক্লাস লিখুন যা যথাযথ সংজ্ঞায়িত কনস্ট্রাক্টরের সাথে থ্রেড প্রসারিত করে যা যথাযথ পরামিতিগুলির সাথে সুপার () কল করে।
জাভা 8 হিসাবে, আপনি কার্যকরভাবে চূড়ান্ত যে পরামিতিগুলি ক্যাপচার করতে ল্যাম্বডা ব্যবহার করতে পারেন । উদাহরণ স্বরূপ:
final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
// Do whatever you want here: param1 and param2 are in-scope!
System.out.println(param1);
System.out.println(param2);
}).start();
জাভা 8-এ আপনি কনকুরન્સી এপিআই এরlambda
সাথে এক্সপ্রেশন ব্যবহার করতে পারেন এবং সরাসরি থ্রেডের সাথে কাজ করার জন্য একটি উচ্চ স্তরের প্রতিস্থাপন হিসাবে:ExecutorService
newCachedThreadPool()
একটি থ্রেড পুল তৈরি করে যা প্রয়োজন অনুসারে নতুন থ্রেড তৈরি করে তবে পূর্বে নির্মিত থ্রেডগুলি উপলব্ধ হলে তা পুনরায় ব্যবহার করবে। এই পুলগুলি সাধারণত অনেক স্বল্পমেয়াদী অ্যাসিনক্রোনাস কার্য সম্পাদন করে এমন প্রোগ্রামগুলির কার্যকারিতা উন্নত করে।
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
executors
জাভাডোকসও দেখুন ।
আমি জানি যে আমি কয়েক বছর দেরি করে এসেছি, তবে আমি এই সমস্যাটি নিয়ে এসে একটি অপ্রথাবাদী পদ্ধতি গ্রহণ করেছি took আমি একটি নতুন ক্লাস না করে এটি করতে চেয়েছিলাম, তাই এটিই আমি নিয়ে এসেছি:
int x = 0;
new Thread((new Runnable() {
int x;
public void run() {
// stuff with x and whatever else you want
}
public Runnable pass(int x) {
this.x = x;
return this;
}
}).pass(x)).start();
শুরু () এবং রান () পদ্ধতিগুলি পেরিয়ে যাওয়া প্যারামিটার:
// Tester
public static void main(String... args) throws Exception {
ThreadType2 t = new ThreadType2(new RunnableType2(){
public void run(Object object) {
System.out.println("Parameter="+object);
}});
t.start("the parameter");
}
// New class 1 of 2
public class ThreadType2 {
final private Thread thread;
private Object objectIn = null;
ThreadType2(final RunnableType2 runnableType2) {
thread = new Thread(new Runnable() {
public void run() {
runnableType2.run(objectIn);
}});
}
public void start(final Object object) {
this.objectIn = object;
thread.start();
}
// If you want to do things like setDaemon(true);
public Thread getThread() {
return thread;
}
}
// New class 2 of 2
public interface RunnableType2 {
public void run(Object object);
}
আপনি রান্নেবল থেকে ক্লাস অর্জন করতে পারেন এবং নির্মাণের সময় (বলুন) প্যারামিটারটি পাস করুন।
তারপরে এটি থ্রেড.স্টার্ট (চলমান r) ব্যবহার করে চালু করুন;
আপনি কি এটি বলতে পারেন থাকাকালীন থ্রেড চলমান হয়, তাহলে কেবল কল থ্রেড আপনার উদ্ভূত বস্তুর একটি রেফারেন্স ধরে রাখুন, এবং কল উপযুক্ত সেটার পদ্ধতি (সিঙ্ক্রোনাইজ যেখানে যথাযথ)
রানবেলগুলিতে পরামিতিগুলি পাস করার একটি সহজ উপায় রয়েছে। কোড:
public void Function(final type variable) {
Runnable runnable = new Runnable() {
public void run() {
//Code adding here...
}
};
new Thread(runnable).start();
}
না আপনি run()
পদ্ধতিটিতে প্যারামিটারগুলি পাস করতে পারবেন না । স্বাক্ষর আপনাকে বলে যে (এটির কোনও পরামিতি নেই)। সম্ভবত এটির সবচেয়ে সহজ উপায় হ'ল উদ্দেশ্যমূলকভাবে নির্মিত অবজেক্ট ব্যবহার করা যা কনস্ট্রাক্টরের একটি প্যারামিটার নেয় এবং এটি একটি চূড়ান্ত ভেরিয়েবলের মধ্যে সঞ্চয় করে:
public class WorkingTask implements Runnable
{
private final Object toWorkWith;
public WorkingTask(Object workOnMe)
{
toWorkWith = workOnMe;
}
public void run()
{
//do work
}
}
//...
Thread t = new Thread(new WorkingTask(theData));
t.start();
একবার আপনি এটি করেন - আপনি যে জিনিসটি 'ওয়ার্কিং টাস্ক' এ পাস করেছেন তার ডেটা অখণ্ডতার বিষয়ে আপনাকে যত্নবান হতে হবে। ডেটা এখন দুটি পৃথক থ্রেডে উপস্থিত থাকবে তাই আপনাকে এটি নিশ্চিত করতে হবে যে এটি থ্রেড নিরাপদ।
আরও একটি বিকল্প; এই পদ্ধতির সাহায্যে আপনি অ্যাসিঙ্ক্রোনাস ফাংশন কলের মতো রান রানযোগ্য আইটেমটি ব্যবহার করতে পারবেন। যদি আপনার কার্যটির কোনও ফলাফল ফেরত দেওয়ার প্রয়োজন না হয়, যেমন এটি কিছু কর্ম সম্পাদন করে তবে কীভাবে আপনি "ফলাফল" পাস করবেন সে সম্পর্কে আপনাকে চিন্তা করার দরকার নেই।
এই প্যাটার্নটি আপনাকে একটি আইটেম পুনরায় ব্যবহার করতে দেয় যেখানে আপনার কোনও ধরণের অভ্যন্তরীণ অবস্থার প্রয়োজন। কনস্ট্রাক্টর কেয়ারে প্যারামিটার (গুলি) পাস না করার সময় প্রোগ্রামগুলির প্যারামিটারগুলিতে অ্যাক্সেসের মধ্যস্থতা করার প্রয়োজন হয়। আপনার ব্যবহারের ক্ষেত্রে বিভিন্ন কলার ইত্যাদি জড়িত থাকলে আপনার আরও চেকের প্রয়োজন হতে পারে You
public class MyRunnable implements Runnable
{
private final Boolean PARAMETER_LOCK = false;
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void setParameter( final X newParameter ){
boolean done = false;
synchronize( PARAMETER_LOCK )
{
if( null == parameter )
{
parameter = newParameter;
done = true;
}
}
if( ! done )
{
throw new RuntimeException("MyRunnable - Parameter not cleared." );
}
}
public void clearParameter(){
synchronize( PARAMETER_LOCK )
{
parameter = null;
}
}
public void run() {
X localParameter;
synchronize( PARAMETER_LOCK )
{
localParameter = parameter;
}
if( null != localParameter )
{
clearParameter(); //-- could clear now, or later, or not at all ...
doSomeStuff( localParameter );
}
}
}
থ্রেড টি = নতুন থ্রেড (নতুন মাইআরনেবল (পরামিতি)); t.start ();
আপনার যদি প্রক্রিয়াজাতকরণের ফলাফলের প্রয়োজন হয় তবে সাব-টাস্ক শেষ হয়ে গেলে আপনাকে MyRunnable এর সমাপ্তির সমন্বয়ও করতে হবে। আপনি কোনও কলটি পাস করতে পারেন বা কেবল থ্রেড 'টি' ইত্যাদির জন্য অপেক্ষা করতে পারেন etc.
কলব্যাকের উদ্দেশ্যে আমি সাধারণত Runnable
ইনপুট প্যারামিটারগুলি দিয়ে নিজের জেনেরিকটি প্রয়োগ করি :
public interface Runnable<TResult> {
void run(TResult result);
}
ব্যবহার সহজ:
myManager.doCallbackOperation(new Runnable<MyResult>() {
@Override
public void run(MyResult result) {
// do something with the result
}
});
পরিচালকের মধ্যে:
public void doCallbackOperation(Runnable<MyResult> runnable) {
new AsyncTask<Void, Void, MyResult>() {
@Override
protected MyResult doInBackground(Void... params) {
// do background operation
return new MyResult(); // return resulting object
}
@Override
protected void onPostExecute(MyResult result) {
// execute runnable passing the result when operation has finished
runnable.run(result);
}
}.execute();
}
আপনার শ্রেণিতে একটি স্থানীয় ভেরিয়েবল তৈরি করুন যা extends Thread
বা implements Runnable
।
public class Extractor extends Thread {
public String webpage = "";
public Extractor(String w){
webpage = w;
}
public void setWebpage(String l){
webpage = l;
}
@Override
public void run() {// l is link
System.out.println(webpage);
}
public String toString(){
return "Page: "+webpage;
}}
আপনি যখন এটি চালান তখন এই পদ্ধতিতে আপনি একটি ভেরিয়েবল পাস করতে পারেন।
Extractor e = new Extractor("www.google.com");
e.start();
আউটপুট:
"www.google.com"