কনকারেন্সি (Concurrency) হল একাধিক কাজ বা থ্রেডকে একসাথে চালানোর ক্ষমতা। Groovy তে কনকারেন্সি ব্যবস্থাপনা বেশ সহজ এবং শক্তিশালী, কারণ এটি Java থ্রেডিং এবং কনকারেন্সি কৌশলগুলিকে মডিফাই বা এক্সটেন্ড করে। Groovy তে বিভিন্ন বিল্ট-ইন কনকারেন্সি মডেল আছে, যা আপনাকে সহজে এবং কার্যকরীভাবে কনকারেন্ট কোড লেখার সুযোগ দেয়।
Groovy তে কনকারেন্সি ব্যবস্থাপনা করার জন্য কিছু প্রধান কৌশল ও টুলস রয়েছে, যেমন গ্যারি (GPars) লাইব্রেরি, ক্লোজার এবং ফিউচার ইত্যাদি। Groovy তে কনকারেন্সি সাধারণত Java থ্রেডিং মডেল এবং Groovy এর ডাইনামিক ফিচারগুলির মাধ্যমে বাস্তবায়িত হয়।
এখানে Groovy তে কনকারেন্সি ব্যবস্থাপনার কিছু গুরুত্বপূর্ণ বিষয় এবং উদাহরণ দেওয়া হলো।
Groovy তে থ্রেডিং খুবই সহজ, কারণ Groovy Java থ্রেডিং মডেলকে সহজ করে তোলে এবং এতে Groovy এর ডাইনামিক বৈশিষ্ট্য ব্যবহার করা যায়। আপনি Groovy তে Thread
ব্যবহার করে থ্রেড তৈরি এবং চালাতে পারেন।
Groovy তে একটি নতুন থ্রেড তৈরি করতে Thread.start()
মেথড ব্যবহার করা হয়।
Thread.start {
println "This is running in a separate thread"
}
println "This is running in the main thread"
এখানে, Thread.start
ব্লকটি একটি নতুন থ্রেড তৈরি করে যা এক্সিকিউট হবে, এবং মেইন থ্রেড তার নিজের কাজ চলতে থাকবে।
আপনি Thread
ব্যবহার করে থ্রেডে বিভিন্ন কার্যক্রম চালাতে পারেন।
Thread.start {
5.times {
println "Running in thread: ${Thread.currentThread().name}"
Thread.sleep(500)
}
}
println "Main thread is running"
এখানে, একটি থ্রেড 5 বার চলবে এবং প্রতি সেকেন্ডে থ্রেডটি কিছু সময় বিরতি নিবে। পাশাপাশি, মেইন থ্রেড নিজস্ব কাজ করবে।
Groovy তে GPars (Groovy Parallel Systems) একটি শক্তিশালী লাইব্রেরি, যা কনকারেন্সি এবং প্যারালাল প্রসেসিংয়ের জন্য ডিজাইন করা হয়েছে। GPars বিভিন্ন কনকারেন্ট টাস্ক পরিচালনা করতে সহায়তা করে, যেমন থ্রেড পুলস, ফিউচারস, স্ট্রিম প্রোসেসিং ইত্যাদি।
GPars লাইব্রেরি ব্যবহার করতে হলে প্রথমে আপনার Groovy প্রকল্পে এটি অন্তর্ভুক্ত করতে হবে। এটি @Grab
অ্যনোটেশন বা Grape
দিয়ে করতে পারেন।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.GParsPool
GParsPool.withPool(4) {
(1..10).eachParallel { println "Processing number $it in thread: ${Thread.currentThread().name}" }
}
এখানে, withPool(4)
ব্যবহার করে আমরা 4টি থ্রেড পুলে প্যারালাল কাজ পরিচালনা করছি। eachParallel
মেথডটি 1 থেকে 10 পর্যন্ত সংখ্যাগুলিকে প্যারালালভাবে প্রক্রিয়া করে।
ফিউচার হল একটি অবজেক্ট যা ভবিষ্যতে সম্পন্ন হবে এমন কোনো অপারেশনের ফলাফল ধারণ করে। এটি কনকারেন্ট টাস্কের ফলাফল পাবার জন্য ব্যবহৃত হয়।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.GParsPool
def future = GParsPool.withPool(1) {
return "Hello from Future!"
}
println future.get() // Output: Hello from Future!
এখানে, future.get()
মেথডটি Future
অবজেক্টের রিটার্ন করা ফলাফল অ্যাক্সেস করে।
Groovy তে ক্লোজার (closures) কনকারেন্সি ব্যবস্থাপনায় খুবই কার্যকরী। eachParallel
বা withPool
এর মতো মেথডের মাধ্যমে ক্লোজার ব্যবহার করা হয় যাতে একাধিক কাজ একসাথে প্যারালালভাবে সম্পাদিত হয়।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.GParsPool
GParsPool.withPool(3) {
(1..6).eachParallel { num ->
println "Processing $num in thread: ${Thread.currentThread().name}"
}
}
এখানে, ক্লোজার ব্যবহার করে 1 থেকে 6 পর্যন্ত সংখ্যাগুলি তিনটি পুল থ্রেডে প্যারালালভাবে প্রক্রিয়া করা হচ্ছে।
Groovy তে Actor Model একটি কনকারেন্সি মডেল, যেখানে আপনি আলাদা আলাদা Actor তৈরি করতে পারেন এবং তাদের মধ্যে মেসেজ পাসের মাধ্যমে কনকারেন্ট কাজ করতে পারেন। Actors সিঙ্গেল থ্রেডে রান করে এবং একে অপরের সাথে মেসেজ আদান-প্রদান করে কাজ করতে পারে।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.actor.Actor
class MyActor extends Actor {
void act() {
println "Actor is processing: $message"
}
}
def actor = new MyActor()
actor.start()
actor << "Hello, Actor!"
এখানে, MyActor
একটি কাস্টম Actor যা মেসেজ প্রক্রিয়া করতে পারে। <<
অপারেটর ব্যবহার করে মেসেজ পাঠানো হচ্ছে।
Groovy তে সিঙ্ক্রোনাইজেশন ব্যবহার করে থ্রেডসের মধ্যে ডেটা রেস কন্ডিশন এড়ানো যায়। আপনি synchronized
ব্লক ব্যবহার করে একই সময় একাধিক থ্রেড একে অপরের ডেটাতে প্রবেশ না করতে নিশ্চিত করতে পারেন।
class Counter {
private int count = 0
def increment() {
synchronized (this) {
count++
}
}
def getCount() {
return count
}
}
def counter = new Counter()
(1..10).eachParallel {
counter.increment()
}
println "Final count: ${counter.getCount()}"
এখানে, synchronized
ব্লক ব্যবহার করে count
ভেরিয়েবলটি সিঙ্ক্রোনাইজ করা হয়েছে, যাতে একাধিক থ্রেড একই সময়ে একে অপরের ডেটাতে পরিবর্তন না করতে পারে।
Groovy তে কনকারেন্সি ব্যবস্থাপনা খুবই শক্তিশালী এবং নমনীয়। Groovy বিভিন্ন কনকারেন্সি কৌশল যেমন থ্রেডিং, GPars, ক্লোজারস, Actors, এবং সিঙ্ক্রোনাইজেশন এর মাধ্যমে কোডের কার্যকারিতা দ্রুত এবং দক্ষভাবে পরিচালনা করতে সহায়তা করে। Groovy তে কনকারেন্সি ব্যবস্থাপনা Java এর থ্রেডিং কৌশলগুলির উপর ভিত্তি করলেও, এর সরল এবং ডাইনামিক বৈশিষ্ট্যগুলি Groovy এর কনকারেন্সি কোড লেখাকে আরও সহজ এবং কার্যকরী করে তোলে।
Groovy তে Concurrency বলতে বোঝায় একাধিক কাজ বা প্রক্রিয়া একই সময়ে সম্পন্ন করার প্রক্রিয়া। Concurrency ব্যবহার করে প্রোগ্রামগুলিকে আরও দক্ষ এবং দ্রুত করা যায়, বিশেষত যেখানে একাধিক কাজ সমান্তরালে সম্পাদন করা হয়। Groovy তে Concurrency ব্যবহারের জন্য থ্রেডিং, GPars
লাইব্রেরি, এবং অন্যান্য Concurrency ইউটিলিটি রয়েছে যা Java এর Concurrency টুলগুলির উপর ভিত্তি করে কাজ করে।
Groovy তে Concurrency ব্যবহারের প্রধান পদ্ধতিগুলি হল:
Groovy তে থ্রেড তৈরি করা খুবই সহজ। Thread
ক্লাস ব্যবহার করে নতুন থ্রেড তৈরি করা যায় এবং Concurrency অর্জন করা সম্ভব।
def task1 = new Thread({
println "Task 1 is running"
sleep(1000)
println "Task 1 completed"
})
def task2 = new Thread({
println "Task 2 is running"
sleep(500)
println "Task 2 completed"
})
task1.start()
task2.start()
এখানে task1
এবং task2
নামে দুটি থ্রেড তৈরি করা হয়েছে এবং start()
মেথডের মাধ্যমে তাদের সমান্তরালে চালানো হচ্ছে।
join
মেথডtask1.join()
task2.join()
println "Both tasks are completed."
join
মেথড ব্যবহার করে একটি থ্রেডের কাজ শেষ হওয়ার জন্য অপেক্ষা করা যায়।
ExecutorService
হলো Java এর একটি Concurrency ফ্রেমওয়ার্ক, যা Groovy তে ব্যবহার করা যায়। এটি থ্রেড পুল ম্যানেজমেন্ট সহজ করে এবং কাস্টম থ্রেড পুল তৈরি করা যায়।
import java.util.concurrent.Executors
def executorService = Executors.newFixedThreadPool(2)
def task1 = {
println "Task 1 is running"
sleep(1000)
println "Task 1 completed"
}
def task2 = {
println "Task 2 is running"
sleep(500)
println "Task 2 completed"
}
executorService.submit(task1 as Runnable)
executorService.submit(task2 as Runnable)
executorService.shutdown()
এখানে Executors.newFixedThreadPool(2)
দিয়ে দুটি থ্রেড নিয়ে একটি থ্রেড পুল তৈরি করা হয়েছে এবং submit()
মেথড ব্যবহার করে কাজ জমা দেওয়া হয়েছে।
Groovy তে GPars লাইব্রেরি Concurrency এবং Parallelism কাজকে আরও সহজ করে তোলে। এটি Actor Model, Dataflow, এবং Parallel Collections সমর্থন করে, যা Concurrency পরিচালনার জন্য অনেক বেশি কার্যকর।
ParallelCollection
ব্যবহার করে Concurrency@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.GParsPool
GParsPool.withPool {
[1, 2, 3, 4, 5].eachParallel { number ->
println "Processing number: $number"
sleep(500)
}
}
println "All tasks completed."
এখানে eachParallel
মেথড ব্যবহার করে একটি লিস্টের প্রতিটি আইটেম সমান্তরালে প্রক্রিয়াকরণ করা হচ্ছে।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.actor.DefaultActor
class SimpleActor extends DefaultActor {
void act() {
loop {
react { message ->
println "Received message: $message"
}
}
}
}
def actor = new SimpleActor()
actor.start()
actor << "Hello, Actor!"
actor << "Another message"
এখানে SimpleActor
নামে একটি Actor তৈরি করা হয়েছে, যা বার্তা প্রাপ্তির জন্য react
মেথড ব্যবহার করে।
Groovy তে Concurrency ব্যবহারের মাধ্যমে সমান্তরালে কাজ করার প্রক্রিয়া সহজ ও কার্যকরী হয়। Groovy তে Concurrency এর জন্য Thread API, ExecutorService, এবং GPars লাইব্রেরি রয়েছে, যা বিভিন্ন প্রয়োজন অনুযায়ী Concurrency পরিচালনা করতে সহায়তা করে। GPars লাইব্রেরি Actor Model, Parallel Collections ইত্যাদি সমর্থন করে যা সমান্তরালে কাজ করার জন্য একটি উন্নত পদ্ধতি প্রদান করে।
Groovy তে Threads এবং Executors ব্যবহৃত হয় concurrrent বা parallel কাজ পরিচালনা করতে, যার মাধ্যমে কোড দ্রুত এবং কার্যকরীভাবে একাধিক টাস্ক পরিচালনা করতে পারে। Groovy Java এর Thread এবং Executor API এর উপর ভিত্তি করে কাজ করে, তবে Groovy এর সিনট্যাক্স খুবই সহজ এবং সংক্ষিপ্ত, যা থ্রেডিং এবং কনকারেন্সি ব্যবস্থাপনাকে আরও সহজ করে তোলে।
Thread একটি ক্লাস যা পারস্পরিকভাবে স্বাধীনভাবে কাজ করতে পারে। Groovy তে থ্রেড তৈরি এবং চালানোর জন্য Java থ্রেডিং API এর Thread
ক্লাস ব্যবহার করা হয়, তবে Groovy তে এটি আরও সংক্ষিপ্তভাবে ব্যবহার করা যায়। সাধারণত, Groovy তে থ্রেড তৈরি করতে আপনি Thread.start() মেথড ব্যবহার করেন।
Thread.start {
println "This is running in a separate thread."
}
println "This is running in the main thread."
উপরের উদাহরণে, Thread.start
ব্যবহার করে একটি নতুন থ্রেড শুরু করা হয়েছে। এর মাধ্যমে "This is running in a separate thread."
স্টেটমেন্ট আলাদা থ্রেডে রান হবে, এবং "This is running in the main thread."
মূল থ্রেডে চলে আসবে।
Groovy তে থ্রেড ব্যবহার করা অনেক সহজ এবং প্রোগ্রামারদের জন্য দ্রুত ফলাফল পাওয়া যায়।
// ফাংশন ডিফাইন করা
def task1 = { println "Task 1 is running" }
def task2 = { println "Task 2 is running" }
// দুইটি আলাদা থ্রেডে কাজ চালানো
Thread.start(task1)
Thread.start(task2)
println "Main thread is running"
এখানে দুটি আলাদা টাস্ক Thread.start()
দিয়ে আলাদা থ্রেডে চালানো হয়েছে, এবং মূল থ্রেডে "Main thread is running"
মেসেজটি প্রদর্শিত হবে।
Executor Groovy তে থ্রেড পরিচালনার আরও উন্নত একটি উপায়, যেটি থ্রেড পুল তৈরি করে এবং স্বয়ংক্রিয়ভাবে থ্রেড ম্যানেজমেন্টের কাজ করে। ExecutorService Groovy তে ব্যবহৃত হয় বিভিন্ন থ্রেড পরিচালনা করার জন্য, যেখানে আপনি একটি থ্রেড পুল তৈরি করতে পারেন।
import java.util.concurrent.*
def executor = Executors.newFixedThreadPool(2)
executor.submit {
println "Task 1 is being executed in thread: ${Thread.currentThread().name}"
}
executor.submit {
println "Task 2 is being executed in thread: ${Thread.currentThread().name}"
}
executor.shutdown()
এখানে একটি FixedThreadPool Executor তৈরি করা হয়েছে যা দুটি থ্রেড পরিচালনা করবে। দুটি টাস্ক একে একে এই থ্রেড পুলে পাঠানো হয়েছে এবং এগুলো থ্রেডে এক্সিকিউট হয়েছে।
import java.util.concurrent.*
def executor = Executors.newFixedThreadPool(3)
def futures = []
// কিছু টাস্ক যোগ করা
futures << executor.submit { println "Task 1 completed" }
futures << executor.submit { println "Task 2 completed" }
futures << executor.submit { println "Task 3 completed" }
// টাস্ক গুলোর ফলাফল প্রাপ্তির জন্য অপেক্ষা করা
futures.each { it.get() }
executor.shutdown()
এখানে submit()
ব্যবহার করে Executor এ কিছু টাস্ক যোগ করা হয়েছে এবং get()
মেথড ব্যবহার করে এই টাস্কগুলোর কাজ শেষ হওয়া পর্যন্ত অপেক্ষা করা হয়েছে। এর মাধ্যমে, আপনি একাধিক কাজ পরিচালনা করতে পারেন এবং একই সময়ে তাদের ফলাফলও পেতে পারেন।
ThreadPoolExecutor Groovy তে ExecutorService এর একটি উন্নত সংস্করণ, যা থ্রেড পুলের আকার এবং তার পরিচালনা আরও উন্নতভাবে ম্যানেজ করতে সাহায্য করে। এটি কাজের জন্য থ্রেড পুলের সংখ্যা কাস্টমাইজ করতে পারে।
import java.util.concurrent.*
def threadPool = new ThreadPoolExecutor(2, 4, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())
// টাস্ক সাবমিট করা
threadPool.submit { println "Task 1 executed" }
threadPool.submit { println "Task 2 executed" }
threadPool.shutdown()
এখানে, ThreadPoolExecutor
ব্যবহার করে একটি থ্রেড পুল তৈরি করা হয়েছে, যা 2 থেকে 4 থ্রেডের মধ্যে কাজ করতে পারে এবং প্রতি 1 সেকেন্ডে একটি নতুন থ্রেড তৈরি করবে।
Groovy তে closures ব্যবহার করে থ্রেড এবং Executors এর সঙ্গে কাজ আরও সহজ করা যায়। Groovy তে closures কে থ্রেড বা Executor এর মাধ্যমে পাঠানো সহজ এবং এর মাধ্যমে কোড আরও ক্লিন এবং সহজ হয়।
def task = { println "Running task in thread ${Thread.currentThread().name}" }
def executor = Executors.newFixedThreadPool(2)
executor.submit(task)
executor.submit(task)
executor.shutdown()
এখানে একটি closure তৈরি করা হয়েছে এবং সেটি submit
মেথডের মাধ্যমে থ্রেডে পাঠানো হয়েছে।
বৈশিষ্ট্য | Thread | Executor |
---|---|---|
থ্রেড ম্যানেজমেন্ট | একক থ্রেড তৈরি ও চালানো | একাধিক থ্রেড তৈরি এবং ম্যানেজমেন্ট |
ব্যবহার | সরাসরি Thread ক্লাস দিয়ে থ্রেড পরিচালনা | ExecutorService দিয়ে থ্রেড পুল তৈরি এবং পরিচালনা |
ব্যবহারিক সুবিধা | সহজ এবং ছোট স্কেল কাজের জন্য উপযুক্ত | বৃহত্তর স্কেল এবং থ্রেড পুল ব্যবস্থাপনা |
Groovy তে Threads এবং Executors ব্যবহারের মাধ্যমে পারলেল বা concurrrent কাজ সহজেই করা যায়। Thread
দ্রুত এবং সরল কাজের জন্য উপযুক্ত, তবে ExecutorService বা ThreadPoolExecutor উন্নত থ্রেড পুল এবং কর্মসম্পাদন ব্যবস্থাপনার জন্য ব্যবহৃত হয়। Groovy তে এগুলোর ব্যবহারে কোড আরও সহজ, পরিষ্কার এবং কার্যকরী হয়।
GPars (Groovy Parallel Systems) হল একটি Groovy ফ্রেমওয়ার্ক যা ডেভেলপারদের জন্য পার্লালেল প্রোগ্রামিং এবং অ্যাসিঙ্ক্রোনাস প্রোগ্রামিং সহজ করে তোলে। GPars Groovy তে পার্লালেল কম্পিউটেশন এবং কনকারেন্সি (concurrency) নিয়ে কাজ করতে ব্যবহৃত হয়, যা বিশেষ করে মাল্টি-কোর প্রসেসরের সুবিধা নিয়ে আরও দ্রুত এবং কার্যকরী কোড তৈরি করতে সাহায্য করে।
GPars ফ্রেমওয়ার্ক Groovy এর ডাইনামিক এবং স্ক্রিপ্টিং ক্ষমতার সাথে একত্রিত হয়ে, পার্লালেল প্রোগ্রামিংকে আরও সহজ, পরিষ্কার এবং দ্রুত করে তোলে।
GPars হল একটি শক্তিশালী এবং কমপ্লেক্স ফিচারযুক্ত লাইব্রেরি যা পার্লালেল প্রোগ্রামিংয়ের জন্য ব্যবহৃত হয়। এটি Groovy তে মাল্টি-থ্রেডিং, অ্যাসিঙ্ক্রোনাস এবং কনকারেন্ট কার্যকারিতা সহজে এবং কার্যকরীভাবে বাস্তবায়ন করার জন্য ডিজাইন করা হয়েছে।
Groovy তে GPars ফ্রেমওয়ার্ক ব্যবহার করতে হলে, প্রথমে আপনি GPars লাইব্রেরিটি আপনার প্রকল্পে যুক্ত করতে হবে। এটি Groovy Grape বা Maven মাধ্যমে করা যেতে পারে।
Grape (Groovy Dependency Manager) ব্যবহার করে:
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
Parallelism হল একটি প্রোগ্রামিং প্যাটার্ন যেখানে একটি কাজকে একাধিক অংশে বিভক্ত করে বিভিন্ন প্রসেসরে একসাথে কার্যকর করা হয়। Groovy তে GPars ব্যবহার করে আপনি সহজেই কোডে পার্লালেল কাজ সম্পন্ন করতে পারেন।
Groovy তে GPars Parallel Collections ব্যবহার করে আপনি একটি List, Set বা Map এর উপাদানগুলির উপর প্যারালাল অপারেশন করতে পারেন। এটি মূলত প্রতিটি উপাদানকে আলাদা থ্রেডে এক্সিকিউট করতে সাহায্য করে।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.GParsPool
def numbers = [1, 2, 3, 4, 5]
GParsPool.withPool {
def squares = numbers.collectParallel { it * it }
println squares
}
আউটপুট:
[1, 4, 9, 16, 25]
এখানে:
GParsPool.withPool
ব্লকের মধ্যে, আমরা collectParallel
মেথড ব্যবহার করেছি, যা প্যারালাল কম্পিউটেশনের মাধ্যমে প্রতিটি উপাদানকে স্কয়ার করে একটি নতুন লিস্ট তৈরি করেছে।Groovy তে GPars ব্যবহার করে আপনি লুপের মধ্যে প্যারালাল অপারেশন চালাতে পারেন।
@Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
import groovyx.gpars.GParsPool
def numbers = [1, 2, 3, 4, 5]
GParsPool.withPool {
numbers.eachParallel { number ->
println "Number: $number, Thread: ${Thread.currentThread().name}"
}
}
আউটপুট:
Number: 1, Thread: pool-1-thread-1
Number: 2, Thread: pool-1-thread-2
Number: 3, Thread: pool-1-thread-3
Number: 4, Thread: pool-1-thread-4
Number: 5, Thread: pool-1-thread-5
এখানে:
eachParallel
মেথড ব্যবহার করা হয়েছে যেখানে প্রতিটি উপাদান আলাদা থ্রেডে প্রক্রিয়া করা হচ্ছে এবং প্রতিটি থ্রেডের নাম প্রিন্ট করা হচ্ছে।GPars Actors Model ব্যবহার করে আপনি সিস্টেমে একাধিক ছোট, স্বাধীন এবং অ্যাসিঙ্ক্রোনাস এক্সিকিউটিং ইউনিট তৈরি করতে পারেন। প্রতিটি অ্যাক্টর নিজের কাজ সম্পন্ন করার পরে অন্য অ্যাক্টরের সাথে যোগাযোগ করতে পারে।
import groovyx.gpars.actor.Actor
import groovyx.gpars.actor.DefaultActor
class MyActor extends DefaultActor {
@Override
void act() {
println "Hello from actor!"
}
}
def actor = new MyActor()
actor.start() // Start the actor to execute the act() method
actor.join() // Wait for actor to finish
এখানে:
act()
মেথডের মাধ্যমে একটি কাজ করবে এবং অন্যদের থেকে আলাদা ভাবে কার্যকর হবে।Futures এবং Promises অ্যাসিঙ্ক্রোনাস অপারেশনগুলি পরিচালনা করতে ব্যবহৃত হয়। Future একটি কমপ্লেক্স কাজের ফলাফল ভবিষ্যতে পাওয়ার জন্য ব্যবহৃত হয়, যখন Promise একটি অপারেশন সম্পন্ন হওয়ার প্রতিশ্রুতি দেয়।
import groovyx.gpars.GParsPool
import groovyx.gpars.dataflow.Dataflow
GParsPool.withPool {
def future = Dataflow.promise {
sleep(1000)
return "Result after 1 second"
}
println future.get() // Output: Result after 1 second
}
এখানে:
get()
মেথড ব্যবহার করে ফলাফল পাওয়া গেছে।GPars ফ্রেমওয়ার্কটি Groovy তে মাল্টি-কোর প্রসেসিং সুবিধা নিয়ে আরও দ্রুত এবং কার্যকরী কোড লেখার জন্য একটি শক্তিশালী টুল।
Groovy, যা Java Virtual Machine (JVM) এর উপর রান করে, Java এর মতো Concurrency (একাধিক থ্রেডের মাধ্যমে একযোগে কাজ) এবং Thread-Safety এর বিষয়গুলোকে সমর্থন করে। যখন একাধিক থ্রেড একে অপরের সাথে ডেটা শেয়ার করে, তখন সেগুলির মধ্যে সঠিক সমন্বয় বজায় রাখাটা গুরুত্বপূর্ণ, যাতে ডেটার কোনো Race Conditions বা অবাঞ্ছিত পরিবর্তন না ঘটে। এই সমস্যা সমাধানে Synchronization এবং Thread-Safety টেকনিকস ব্যবহৃত হয়।
Groovy তে, Java এর synchronized
ব্লক এবং অন্যান্য থ্রেড-সেফ মেকানিজমের পাশাপাশি Groovy এর সহজ সিনট্যাক্স এবং টুলস ব্যবহার করে আপনি কনকারেন্সি এবং থ্রেড-সেফ প্রোগ্রাম তৈরি করতে পারেন।
এখানে Synchronization এবং Thread-Safety এর টেকনিকস আলোচনা করা হলো।
Synchronization হল একটি পদ্ধতি যার মাধ্যমে আপনি নিশ্চিত করেন যে একাধিক থ্রেড একই সময়ে একটি ক্রিটিকাল সেকশনে প্রবেশ করতে পারে না। যখন একাধিক থ্রেড একসাথে একটি ডেটা বা মেথড অ্যাক্সেস করে, তখন এটি সঠিকভাবে কাজ না করতে পারে (এটা Race Condition তৈরি করতে পারে)। Synchronization এর মাধ্যমে এই সমস্যা এড়ানো হয়।
Groovy তে synchronized
কিওয়ার্ড ব্যবহার করে আপনি একটি মেথডকে সিঙ্ক্রোনাইজ করতে পারেন, যাতে একাধিক থ্রেড একই মেথড একসাথে এক্সিকিউট না করতে পারে।
class Counter {
private int count = 0
// Synchronized method
synchronized void increment() {
count++
}
int getCount() {
return count
}
}
def counter = new Counter()
// Simulating two threads accessing increment method
def thread1 = new Thread({ counter.increment() })
def thread2 = new Thread({ counter.increment() })
thread1.start()
thread2.start()
thread1.join()
thread2.join()
println counter.getCount() // Output: 2
এখানে, increment()
মেথড সিঙ্ক্রোনাইজ করা হয়েছে, যাতে একসাথে একাধিক থ্রেড একই সময়ে count
এর মান পরিবর্তন করতে না পারে।
আপনি শুধু নির্দিষ্ট অংশের কোডকে সিঙ্ক্রোনাইজ করতে চান, তবে synchronized
ব্লক ব্যবহার করতে পারেন। এটি থ্রেড-সেফ কোড ব্লক তৈরি করতে সহায়তা করে।
class Counter {
private int count = 0
void increment() {
synchronized(this) {
count++
}
}
int getCount() {
return count
}
}
def counter = new Counter()
// Simulating two threads accessing increment method
def thread1 = new Thread({ counter.increment() })
def thread2 = new Thread({ counter.increment() })
thread1.start()
thread2.start()
thread1.join()
thread2.join()
println counter.getCount() // Output: 2
এখানে, synchronized(this)
ব্লকটি শুধুমাত্র count
পরিবর্তন করার অংশকে সিঙ্ক্রোনাইজ করেছে, যাতে দুটি থ্রেড একসাথে এই অংশে প্রবেশ না করতে পারে।
Thread-Safety নিশ্চিত করার জন্য বিভিন্ন টেকনিক ব্যবহার করা হয়, যাতে একাধিক থ্রেড একসাথে ডেটা অ্যাক্সেসের সময় কোনো সমস্যা না ঘটে।
Groovy তে volatile
ভেরিয়েবল ব্যবহার করা হয় যেগুলি একাধিক থ্রেডের মধ্যে শেয়ার করা হয়। এটি নিশ্চিত করে যে ভেরিয়েবলটি কোনো একটি থ্রেড দ্বারা পরিবর্তন হলে তা অন্য সমস্ত থ্রেডের কাছে সঠিকভাবে আপডেট হবে।
class SharedResource {
volatile boolean flag = false
void setFlag(boolean value) {
flag = value
}
boolean getFlag() {
return flag
}
}
def resource = new SharedResource()
// Thread 1
def thread1 = new Thread({
resource.setFlag(true)
})
// Thread 2
def thread2 = new Thread({
while (!resource.getFlag()) {
// Waiting for flag to become true
}
println "Flag was set to true!"
})
thread1.start()
thread2.start()
thread1.join()
thread2.join()
এখানে, volatile
ভেরিয়েবল flag
ব্যবহার করা হয়েছে, যাতে যখন থ্রেড একটি ভেরিয়েবল পরিবর্তন করে, সেটি অন্য থ্রেডে সঠিকভাবে প্রতিফলিত হয়।
Groovy তে আপনি Java এর ReentrantLock
ব্যবহার করে লকিং মেকানিজমও প্রয়োগ করতে পারেন। এটি সিঙ্ক্রোনাইজেশনের চেয়ে আরও বেশি নিয়ন্ত্রণ দেয়।
import java.util.concurrent.locks.ReentrantLock
class Counter {
private int count = 0
private final ReentrantLock lock = new ReentrantLock()
void increment() {
lock.lock()
try {
count++
} finally {
lock.unlock()
}
}
int getCount() {
return count
}
}
def counter = new Counter()
// Simulating two threads accessing increment method
def thread1 = new Thread({ counter.increment() })
def thread2 = new Thread({ counter.increment() })
thread1.start()
thread2.start()
thread1.join()
thread2.join()
println counter.getCount() // Output: 2
এখানে, ReentrantLock
ব্যবহার করে increment()
মেথডের উপরে লক প্রয়োগ করা হয়েছে। এটি কোডের অংশের উপর আরও নিয়ন্ত্রিত সিঙ্ক্রোনাইজেশন সরবরাহ করে।
Groovy তে, atomic variables ব্যবহার করা যেতে পারে যখন একাধিক থ্রেড একই ভেরিয়েবল অ্যাক্সেস করে। Java এর AtomicInteger
বা AtomicReference
Groovy তে সরাসরি ব্যবহৃত হতে পারে। এটি lock-free অপারেশন প্রদান করে।
import java.util.concurrent.atomic.AtomicInteger
class Counter {
private final AtomicInteger count = new AtomicInteger(0)
void increment() {
count.incrementAndGet()
}
int getCount() {
return count.get()
}
}
def counter = new Counter()
// Simulating two threads accessing increment method
def thread1 = new Thread({ counter.increment() })
def thread2 = new Thread({ counter.increment() })
thread1.start()
thread2.start()
thread1.join()
thread2.join()
println counter.getCount() // Output: 2
এখানে, AtomicInteger
ব্যবহার করা হয়েছে যাতে atomic operations নিশ্চিত করা যায় এবং থ্রেড-সেফভাবে ভেরিয়েবলটি ইনক্রিমেন্ট করা যায়।
Groovy তে Threading সহজ করার জন্য কিছু বিল্ট-ইন বৈশিষ্ট্য রয়েছে, যেমন GPars
(Groovy Parallel Systems) লাইব্রেরি, যা থ্রেড পুল, ফিউচারস এবং পারালাল প্রসেসিংয়ের জন্য ব্যবহৃত হয়।
Groovy তে GPars লাইব্রেরি ব্যবহার করে পারালাল থ্রেডিং সহজে করা যায়।
@Grab(group='org.codehaus.groovy', module='groovy-all', version='2.4.7')
import groovyx.gpars.GParsPool
GParsPool.withPool {
(1..5).eachParallel { num ->
println "Thread $num is running"
}
}
এখানে, eachParallel
মেথডের মাধ্যমে পাঁচটি থ্রেড একসাথে রান করা হয়েছে।
Groovy তে Synchronization এবং Thread-Safety নিশ্চিত করার জন্য বিভিন্ন টেকনিক ব্যবহৃত হয়:
volatile
, ReentrantLock
, এবং Atomic
ক্লাস ব্যবহার করা যেতে পারে।Groovy তে এই টেকনিকসের মাধ্যমে আপনি সহজেই থ্রেড-সেফ প্রোগ্রাম তৈরি করতে পারেন এবং একাধিক থ্রেডের মধ্যে সঠিক সমন্বয় বজায় রাখতে পারেন।
common.read_more