11 Eylül 2019 Çarşamba

Future Arayüzü

Future
Future aslında bir arayüzdür. Amacı iki thread arasında birinin döndürdüğü sonucu diğerine ulaştırmak için köprü kurmaktır.

Bu arayüzden kalıtan sınıflar şöyle
ForkJoinTask, FutureTask, RecursiveAction, RecursiveTask, SwingWorker

Future arayüzü reactive programlama için değildir. Bu iş için CompletableFuture kullanılır.

Executer sınıfının submit metodu Future döner. Şöyle yaparız.
Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
    System.out.println("Asynchronous Callable");
    return "Callable Result";
}});

cancel metodu
İmzası şöyle.
public boolean cancel(boolean mayInterruptIfRunning);
Future cancel() edildikten sonra get() metodunu çağırmak CancellationException fırlatılmasına sebep olur

Örnek
Şöyle yaparız
Future<String> future = ...
future.cancel(true);
Örnek - interrupt yapmaz
Şöyle yaparız. Bu örnekte thread interrupt edilmediği için thread'in bitmesi için yapması gereken şey future nesnesinin isCalled() metodunu kullanarak döngüden çıkıp çıkmayacağın bakması
FutureTask<String> task = new FutureTask<String>(new Callable<String>() {

    @Override
    public String call() throws Exception {
        while (!task.isCancelled()) {
            System.out.println("Running...");
            Thread.sleep(1000);
        }
        return "The End";
    }

});

new Thread(task).start();
Thread.sleep(1500);
task.cancel(false);
Örnek - interrupt yapar
Şöyle yaparız. Bu örnekte thread future.cancel(true) ile çağrılıyor ve döngüden çıkmak için Thread.interrupted() ile koşulu kontrol ediyor.
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
  while (true) {
    ...
    if (Thread.interrupted()) {
      return;
    }
  }
}, 1, 2, TimeUnit.SECONDS);
Örnek - interrupt yapar
Elimizde şöyle bir kod olsun. Bu sınıfın readLine() metodu Executor içinde okuma işlemi yapar. Eğer readLine() bloke olmuş beklerken cancel() metodu çağrılırsa null döner.
public class CancelableReader extends BufferedReader {

  private final ExecutorService executor;
  private Future future;

  public CancelableReader(Reader in) {
    super(in);
    executor = Executors.newSingleThreadExecutor();
  }

  @Override
  public String readLine() {

    future = executor.submit(super::readLine);

    try {
      return (String) future.get();
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    } catch (CancellationException e) {
      return null;
    }

    return null;

  }

  public void cancelRead() {
    future.cancel(true);
  }
}

get metodu
Elimizde farklı Callable nesneleri olsun.
public class One implements Callable<Integer> {

  public Integer call() throws Exception {
    print("One...");
    Thread.sleep(6000);
    print("One!!");
    return 100;
  }
}

public class Two implements Callable<String> {

  public String call() throws Exception {
    print("Two...");
    Thread.sleep(1000);
    print("Two!!");
    return "Done";
  }
}

public class Three implements Callable<Boolean> {

  public Boolean call() throws Exception {
    print("Three...");
    Thread.sleep(2000);
    print("Three!!");
    return true;
  }
}
Bu nesneleri bir Executor'a verip sonuçları almak için şöyle yaparız.
int n = 3;
// Build a fixed number of thread pool
ExecutorService pool = Executors.newFixedThreadPool(n);
// Wait until One finishes it's task.
pool.submit(new One()).get();
// Wait until Two finishes it's task.
pool.submit(new Two()).get();
// Wait until Three finishes it's task.
pool.submit(new Three()).get();
pool.shutdown();
Çıktı olarak şunu alırız.
One...
One!!
Two...
Two!!
Three...
Three!!
get metodu - timeout
TimeoutException fırlatabilir.

Örnek
Şöyle yaparız.
Future<String> future = ...;
try {
  future.get(5, TimeUnit.SECONDS); //timeout is in 5 seconds
} 
catch (TimeoutException e) {
  System.err.println("Timeout");
  future.cancel(true);
}
Örnek
Şöyle yaparız.
ExecutorService executor = Executors.newSingleThreadExecutor();
String string = null;
try {
  Future<String> future = executor.submit(new Callable<String>() {
    public String call() throws Exception {
      // your expensive operation here.
      return "result";
      }
    });
    // Set timeout
    string = future.get(1, TimeUnit.SECONDS);
  } catch (TimeoutException e) {
    // handle timeout here or write a ExceptionMapper for TimeoutException.
  } finally {
    executor.shutdownNow();
}
isCancelled metodu
Örnek ver

isDone metodu
Şöyle yaparız.
if (future.isDone()){
  //do something
}
Future İle Paralelleştirme Örnekleri
Elimizde sadece Java 7 varsa şöyle yaparız.
ResultSet rows = ...; 

List<Future<?>> futures = new ArrayList<>();
while(rows.next())
{
  
  String path = rows.getString("path");
  int job_id = rows.getInt("job_id");
  futures.add(executor.submit(new Runnable() {
    @Override
    public void run() {
      ...
    }
  });
}
// Wait until all finished
for(Future<?> future : futures)
  futures.get();
Kendi Future Sınıfmız
Şöyle yaparız.
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean succeeded = new AtomicBoolean();

public void set (Boolean value)) {
  succeeded.set (value);
  semaphore.release();
}

public Boolean get () {
  semaphore.acquire ();
  return succeeded.get();

}


Hiç yorum yok:

Yorum Gönder