জাভাতে কীভাবে অবিচ্ছিন্নভাবে কোনও পদ্ধতি কল করা যায়


126

আমি ইদানীং গো-এর গোরোটাইনগুলিতে দেখছি এবং ভেবেছিলাম জাভাতেও এরকম কিছু পাওয়া ভাল লাগবে। যতদূর আমি একটি পদ্ধতি কলকে সমান্তরাল করার সাধারণ উপায়টি অনুসন্ধান করেছি এরকম কিছু করা:

final String x = "somethingelse";
new Thread(new Runnable() {
           public void run() {
                x.matches("something");             
    }
}).start();

এটি খুব মার্জিত নয়। এটি করার আরও ভাল উপায় আছে?একটি প্রকল্পে আমার এই জাতীয় সমাধানের প্রয়োজন ছিল তাই আমি সিদ্ধান্ত নিয়েছি যে আমার নিজের র‌্যাপার ক্লাসটি একটি অ্যাসিঙ্ক পদ্ধতির কলকে ঘিরে বাস্তবায়ন করব।

আমি জে- গোতে আমার মোড়ক ক্লাস প্রকাশ করেছি । তবে আমি জানি না এটি ভাল সমাধান কিনা। ব্যবহার সহজ:

SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10);         //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get());           //Blocks until intReturningMethod returns

বা কম ভার্বোস:

Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady())                //Blocks until myRandomMethod has ended
    System.out.println("Method is finished!");

অভ্যন্তরীণভাবে আমি এমন একটি ক্লাস ব্যবহার করছি যা রান্নেবলকে কার্যকর করে এবং সঠিক পদ্ধতি অবজেক্টটি পেতে এবং এটিতে অনুরোধ করার জন্য কিছু প্রতিবিম্ব কাজ করে।

আমি আমার ক্ষুদ্র গ্রন্থাগার সম্পর্কে এবং জাভাতে এ্যাসিঙ্ক পদ্ধতি কল করার বিষয়ে কিছু মতামত চাই। এটি নিরাপদ? ইতিমধ্যে একটি সহজ উপায় আছে?


1
আপনি কি আবার আপনার J-Go lib কোডটি দেখাতে পারবেন?
মিসানজেল

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

2
দুর্দান্ত প্রশ্ন !! জাভা 8 এটির জন্য কমপ্লেটেবল ফিউচার সরবরাহ করে। অন্যান্য উত্তরগুলি জাভা
প্রোগ্রামার

উত্তর:


155

আমি সবেমাত্র আবিষ্কার করেছি যে আপনার কাজ করার একটি পরিষ্কার উপায় আছে

new Thread(new Runnable() {
    public void run() {
        //Do whatever
    }
}).start();

(কমপক্ষে জাভা 8 এ), আপনি এটিকে সংক্ষিপ্ত করতে ল্যাম্বডা এক্সপ্রেশনটি ব্যবহার করতে পারেন:

new Thread(() -> {
    //Do whatever
}).start();

জেএসে কোনও ফাংশন করার মতো সহজ!


আপনার উত্তরটি আমার সমস্যাটিকে সহায়তা করেছে - stackoverflow.com/questions/27009448/… । আমার পরিস্থিতিটি প্রয়োগ করতে খুব অসুবিধাজনক, তবে শেষ পর্যন্ত এটি কার্যকর হয়েছিল :)
ডেকার্ড

পরামিতি দিয়ে কল কিভাবে?
ইয়াতানাডাম

2
@ আয়তনাদম এটি আপনার প্রশ্নের উত্তর দিতে পারে। উপরের কোডটি কেবল কোনও পদ্ধতির ভিতরে রাখুন এবং আপনার মত চলকটি আটকে দিন। আমি আপনার জন্য তৈরি এই পরীক্ষার কোডটি দেখুন
user3004449

1
@eNnillaMS থ্রেড চালানোর পরে কি থামানো উচিত? এটি কি স্বয়ংক্রিয়ভাবে বন্ধ হয় বা আবর্জনা সংগ্রহকারী দ্বারা ?
ব্যবহারকারী3004449

@ user3004449 থ্রেড স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়, তবে আপনি এটি জোর করেও করতে পারেন।
শান

58

জাভা 8 প্রবর্তিত কমপ্লেটেবলফিউচার প্যাকেজটিতে উপলব্ধ java.util.concurrent.CompletableF ভবিষ্যত, একটি অ্যাসিঞ্চ কল করতে ব্যবহার করা যেতে পারে:

CompletableFuture.runAsync(() -> {
    // method call or code to be asynch.
});

CompletableFutureঅন্য উত্তরে উল্লেখ করা হয়েছিল, তবে সে পুরো supplyAsync(...)শৃঙ্খলটি ব্যবহার করেছে । এটি একটি সাধারণ মোড়ক যা প্রশ্নকে পুরোপুরি ফিট করে।
এনডিএম 13

ForkJoinPool.commonPool().execute()ওভারহেড কিছুটা কম রয়েছে
মার্ক জেরোনিমাস

31

আপনি ক্লাস বিবেচনা করতে ইচ্ছুক হতে পারে java.util.concurrent.FutureTask

আপনি যদি জাভা 5 বা তার পরে ব্যবহার করছেন তবে ফিউচারটাস্ক "একটি বাতিলযোগ্য অ্যাসিনক্রোনাস গণনা" এর টার্নকি বাস্তবায়ন।

java.util.concurrentপ্যাকেজটিতে আরও সমৃদ্ধ অ্যাসিনক্রোনাস এক্সিকিউশন শিডিউলিং আচরণ রয়েছে (উদাহরণস্বরূপ ScheduledExecutorService), তবে FutureTaskআপনার প্রয়োজনীয় সমস্ত কার্যকারিতা থাকতে পারে।

আমি এমনকি এতদূর গিয়েও বলতে পারি যে FutureTaskউপলব্ধ হওয়ার পরে আপনি উদাহরণ হিসাবে যে প্রথম কোড প্যাটার্নটি দিয়েছেন তা ব্যবহার করার পরামর্শ দেওয়া হয় না। (ধরে নিচ্ছেন আপনি জাভা 5 বা তার পরে আছেন))


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

আমি আপনাকে শুনতে পাচ্ছি. জাভাতে (এখনও) প্রথম শ্রেণির ফাংশন নেই, সুতরাং এই মুহূর্তে শিল্পের অবস্থা।
ছায়াময়

ভবিষ্যতের কীওয়ার্ডগুলির জন্য ধন্যবাদ ... এখন আমি সেগুলি সম্পর্কে টিউটোরিয়ালগুলি খুলছি ... খুব দরকারী। : D
gumuruh

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

24

আমি এর জন্য প্রতিবিম্ব ব্যবহার করার ধারণা পছন্দ করি না।
এটি কিছু রিফ্যাক্টরিংয়ে হারিয়ে যাওয়ার জন্য কেবল বিপজ্জনক নয়, তবে এটি দ্বারাও অস্বীকার করা যেতে পারে SecurityManager

FutureTaskjava.util.concurrent প্যাকেজ থেকে অন্যান্য বিকল্প হিসাবে একটি ভাল বিকল্প।
সাধারণ কাজের জন্য আমার প্রিয়:

    Executors.newSingleThreadExecutor().submit(task);

একটি থ্রেড তৈরি করার চেয়ে সামান্য সংক্ষিপ্ত (টাস্ক কলযোগ্য বা একটি চলমান


1
জিনিসটি হ'ল আমি কেবল একটি পদ্ধতি কল প্রয়োগ করতে চাই। এইভাবে আমাকে লক্ষ্য শ্রেণীর প্রয়োগ পরিবর্তন করতে হবে। আমি যে জিনিসটি চেয়েছিলাম তা হ'ল কলটি হ'ল রান্নেবল বা কলযোগ্যকে অভিশংসনের বিষয়ে চিন্তা না করেই
ফিলিপ হুমেল

তাহলে এটি আরও সাহায্য করবে না :( তবে সাধারণত আমি প্রতিবিম্বের পরিবর্তে একটি রান্নেবল বা কলযোগ্য ব্যবহার করতে পছন্দ করবো
user85421

4
একটি সংক্ষিপ্ত দ্রষ্টব্য: ExecutorServiceউদাহরণটি ট্র্যাক রাখা এটি আরও সুন্দর , যাতে আপনার shutdown()যখন প্রয়োজন তখন ফোন করতে পারেন।
ড্যানিয়েল স্যাজলে

1
আপনি যদি এটি করেন তবে আপনি কী জেএমএমকে শাটডাউন করতে অস্বীকার করার কারণে অব্যবহারকারী অ্যাসিিকিউটর সার্ভিসটি শেষ করবেন না? আমি একক থ্রেডযুক্ত, সময়-সীমাবদ্ধ, এক্সিকিউটর সার্ভিস পেতে আপনার নিজস্ব পদ্ধতি লেখার পরামর্শ দেব।
jangofan

14

আপনি কমপ্লিটেবল ফিউচারের জন্য জাভা 8 সিনট্যাক্সটি ব্যবহার করতে পারেন, আপনি যেমন একটি অ্যাসিঙ্ক ফাংশন কল করে ফলাফলের ভিত্তিতে অতিরিক্ত অ্যাসিঙ্ক কম্পিউটেশন সম্পাদন করতে পারেন।

উদাহরণ স্বরূপ:

 CompletableFuture.supplyAsync(this::findSomeData)
                     .thenApply(this:: intReturningMethod)
                     .thenAccept(this::notify);

আরও বিশদ এই নিবন্ধে পাওয়া যাবে


10

আপনি jcabi- দিকগুলি এবং AspectJ @Asyncথেকে টিকাটি ব্যবহার করতে পারেন :

public class Foo {
  @Async
  public void save() {
    // to be executed in the background
  }
}

আপনি যখন কল করবেন তখন save()একটি নতুন থ্রেড শুরু হয় এবং এর শরীরকে কার্যকর করে। আপনার মূল থ্রেড ফলাফলের জন্য অপেক্ষা না করেই চলতে থাকে save()


1
নোট করুন যে এই পদ্ধতিটি অ্যাসিক্রোনাস সংরক্ষণের জন্য সমস্ত কল করবে, যা আমরা যা চাই তা হতে পারে বা নাও পারে। ক্ষেত্রে যখন কোনও প্রদত্ত পদ্ধতিতে কেবলমাত্র কিছু কলকে async করা উচিত, এই পৃষ্ঠায় প্রস্তাবিত অন্যান্য পন্থাগুলি ব্যবহার করা যেতে পারে।
বোমরিন

আমি কি এটি কোনও ওয়েব অ্যাপ্লিকেশনে ব্যবহার করতে পারি (যেহেতু থ্রেডগুলি পরিচালনা করার প্রস্তাব দেওয়া হয় না)?
onlinenaman

8

আপনি এটির জন্য ফিউচার-অ্যাসিঙ্করসাল্ট ব্যবহার করতে পারেন।

@Async
public Future<Page> findPage(String page) throws InterruptedException {
    System.out.println("Looking up " + page);
    Page results = restTemplate.getForObject("http://graph.facebook.com/" + page, Page.class);
    Thread.sleep(1000L);
    return new AsyncResult<Page>(results);
}

তথ্যসূত্র: https://spring.io/guides/gs/async-method/


10
যদি আপনি স্প্রিং-বুট ব্যবহার করেন।
জিওভান্নি টরাল্ডো

6

জাভা অ্যাসিঙ্ক পদ্ধতিগুলি কল করার একটি দুর্দান্ত উপায়ও সরবরাহ করে। মধ্যে java.util.concurrent আমরা আছে ExecutorService যে একই করছেন সাহায্য করে। আপনার অবজেক্টটি এভাবে শুরু করুন -

 private ExecutorService asyncExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

এবং তারপরে এই ফাংশনটি কল করুন-

asyncExecutor.execute(() -> {

                        TimeUnit.SECONDS.sleep(3L);}

3

এটি সম্ভবত আসল সমাধান নয়, তবে এখন - জাভা 8-এ আপনি ল্যাম্বডা এক্সপ্রেশনটি ব্যবহার করে এই কোডটি কমপক্ষে কিছুটা আরও ভাল দেখতে পারেন।

final String x = "somethingelse";
new Thread(() -> {
        x.matches("something");             
    }
).start();

এবং আপনি এটি এক লাইনেও করতে পারেন, এখনও এটি বেশ পাঠযোগ্য।

new Thread(() -> x.matches("something")).start();

এটা এই জাভা ব্যবহার 8. ব্যবহার করতে সত্যিই চমৎকার
মুক্তির

3

আপনি ক্যাকটুসAsyncFunc থেকে ব্যবহার করতে পারেন :

boolean matches = new AsyncFunc(
  x -> x.matches("something")
).apply("The text").get();

এটি পটভূমিতে কার্যকর করা হবে এবং ফলাফল get()হিসাবে এটি উপলব্ধ হবে Future


2

এটি সত্যিকারের সাথে সম্পর্কিত নয় তবে যদি আমি অবিচ্ছিন্নভাবে কোনও পদ্ধতিতে কল করতে পারি যেমন ম্যাচগুলি (), তবে আমি ব্যবহার করব:

private final static ExecutorService service = Executors.newFixedThreadPool(10);
public static Future<Boolean> matches(final String x, final String y) {
    return service.submit(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            return x.matches(y);
        }

    });
}

তারপরে অ্যাসিক্রোনাস পদ্ধতিটি কল করতে আমি এটি ব্যবহার করব:

String x = "somethingelse";
try {
    System.out.println("Matches: "+matches(x, "something").get());
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

আমি এটি পরীক্ষা করেছি এবং এটি কাজ করে। কেবল ভেবেছিলেন যে অন্যরা যদি কেবল "অ্যাসিনক্রোনাস পদ্ধতিতে" আসে তবে এটি তাদের সহায়তা করতে পারে।


1

EA দ্বারা নির্মিত Async-Await এর জন্য একটি দুর্দান্ত লাইব্রেরি রয়েছে: https://github.com/electronicarts/ea-async

তাদের রেডমি থেকে:

EA Async সহ

import static com.ea.async.Async.await;
import static java.util.concurrent.CompletableFuture.completedFuture;

public class Store
{
    public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
    {
        if(!await(bank.decrement(cost))) {
            return completedFuture(false);
        }
        await(inventory.giveItem(itemTypeId));
        return completedFuture(true);
    }
}

EA Async ছাড়া

import static java.util.concurrent.CompletableFuture.completedFuture;

public class Store
{
    public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
    {
        return bank.decrement(cost)
            .thenCompose(result -> {
                if(!result) {
                    return completedFuture(false);
                }
                return inventory.giveItem(itemTypeId).thenApply(res -> true);
            });
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.