Aşağıda paralel çalışırken karşıma çıkan örüntülerle ilgili notlarım var.
ThreadPool ile Birbirinden Bağımsız İşlerin Çalıştırılması
Bu en kolay örüntü. ExecutorService'e verilen işin sonucu beklememiz gerekmiyor. Özellikle execute() metodu bu örüntü ile kullanmak için yazılmış.
ThreadPool Olmadan Çalıştırılan Tek Bir İşin Bitmesinin Beklenmesi
Hemen hemen tüm thread kütüphaneleri join isminde bir metod sağlıyorlar. Aşağıdaki bir kaç örnek var.
C#
Örneği buradan aldım.
ThreadPool ile Çalıştırılan Tek Bir İşin Bitmesinin Beklenmesi
C#
Örneği buradan aldım.
Eğer TPL kullanılıyorsa aşağıdaki gibi yapılabilir.
ThreadPool ile Çalıştırılan Tek Bir İşin Bitmesinin Beklenmesi ve Sonucunun Alınması
Java
Executor.execute metodu ile
Bu örüntüde FutureTask kullanılıyor. FutureTask ile işin bitip bitmediği kontrol edilebilir ve gerekirse iş iptal de edilebilir ancak dikkat edilmesi gereken bir nokta var. FutureTask tekrar tekrar kullanılamaz.
FutureTask ya Runnable ya da Callable arayüzününden birisini saran bir sınıf. Runnable arayüzü en eski arayüz ve bir sonuç tipi döndüremiyor çünkü sadece void run() metoduna sahip. Callable arayüzü ise bir sonuç döndürebiliyor çünkü V call() metoduna sahip.
Buradan aldığım örnekte cache içinde önceden hesaplanmış bir sonuç varsa kullanılıyor. Yoksa hesaplam işleminin bitmesi bekleniyor.
Örneği buradan aldım.Future.get() metodu bu sefer timeout mekanizması ile beraber kullanılıyor.
ThreadPool ile Çalıştırılan Birden Fazla İşin Sonucunun Alınması
Java
Bu örüntüde CompletionService kullanılıyor. Buradan aldığım örnekte tek bir işin sonucunun gelmesi ile diğer görevler iptal ediliyor.
Paralel For ve ForEach Döngüleri
“Parallel.For” for Java? sorusunda bazı döngülerin nasıl paralel çalıştırılabileceği gösterilmiş.Aşağıdaki soruda C# ile for each döngüsü kurulurken, döngüdeki değişkenin kullanılmaması gerektiği gösterilmiş. Örnek:
ThreadPool ile Birbirinden Bağımsız İşlerin Çalıştırılması
Bu en kolay örüntü. ExecutorService'e verilen işin sonucu beklememiz gerekmiyor. Özellikle execute() metodu bu örüntü ile kullanmak için yazılmış.
ThreadPool Olmadan Çalıştırılan Tek Bir İşin Bitmesinin Beklenmesi
Hemen hemen tüm thread kütüphaneleri join isminde bir metod sağlıyorlar. Aşağıdaki bir kaç örnek var.
C#
Örneği buradan aldım.
ThreadPool ile Çalıştırılan Tek Bir İşin Bitmesinin Beklenmesi
C#
Örneği buradan aldım.
Eğer TPL kullanılıyorsa aşağıdaki gibi yapılabilir.
Task t = Task.Factory.StartNew(() => Console.WriteLine("Started"););
t.Wait();
ThreadPool ile Çalıştırılan Tek Bir İşin Bitmesinin Beklenmesi ve Sonucunun Alınması
Java
Executor.execute metodu ile
Bu örüntüde FutureTask kullanılıyor. FutureTask ile işin bitip bitmediği kontrol edilebilir ve gerekirse iş iptal de edilebilir ancak dikkat edilmesi gereken bir nokta var. FutureTask tekrar tekrar kullanılamaz.
FutureTask ya Runnable ya da Callable arayüzününden birisini saran bir sınıf. Runnable arayüzü en eski arayüz ve bir sonuç tipi döndüremiyor çünkü sadece void run() metoduna sahip. Callable arayüzü ise bir sonuç döndürebiliyor çünkü V call() metoduna sahip.
Buradan aldığım örnekte cache içinde önceden hesaplanmış bir sonuç varsa kullanılıyor. Yoksa hesaplam işleminin bitmesi bekleniyor.
public class Cache<K, V> {Executor.submit metodu ile
ConcurrentMap<K, FutureTask<V>> map = new ConcurrentHashMap();
Executor executor = Executors.newFixedThreadPool(8);
public V get(final K key) {
FutureTask<V> f = map.get(key);
if (f == null) {
Callable<V> c = new Callable<V>() {
public V call() {
// return value associated with key
}
};
f = new FutureTask<V>(c);
FutureTask old = map.putIfAbsent(key, f);
if (old == null)
executor.execute(f);
else
f = old;
}
return f.get();
}
}
Örneği buradan aldım.Future.get() metodu bu sefer timeout mekanizması ile beraber kullanılıyor.
ThreadPool ile Çalıştırılan Birden Fazla İşin Sonucunun Alınması
Java
Bu örüntüde CompletionService kullanılıyor. Buradan aldığım örnekte tek bir işin sonucunun gelmesi ile diğer görevler iptal ediliyor.
void solve(Executor e, Collection<Callable<Result>> solvers)Yukarıdaki kodda dikkat edilmesi gereken nokta Future.cancel() metodunun çağırılması. Bu metod alt tarafta Thread.interrupt() metodunu çağırır. Eğer bizim threadimiz aşağıdaki gibi çalışmıyorsa aslında Future.cancel() metodu işe yaramayabilir.
throws InterruptedException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
int n = solvers.size();
List<Future<Result>> futures = new ArrayList<Future<Result>>(n);
Result result = null;
try {
for (Callable<Result> s : solvers)
futures.add(ecs.submit(s));
for (int i = 0; i < n; ++i) {
try {
Result r = ecs.take().get();
if (r != null) {
result = r;
break;//Diğer işlerin bitmesini bekleme
}
} catch(ExecutionException ignore) {}
}
}
finally {
for (Future<Result> f : futures)
f.cancel(true);
}
if (result != null)
use(result);
}
while(!Thread.currentThread().isInterrupted()){
try{
// birşeyler yap
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
Paralel For ve ForEach Döngüleri
“Parallel.For” for Java? sorusunda bazı döngülerin nasıl paralel çalıştırılabileceği gösterilmiş.Aşağıdaki soruda C# ile for each döngüsü kurulurken, döngüdeki değişkenin kullanılmaması gerektiği gösterilmiş. Örnek: