17 Eylül 2018 Pazartesi

LockSupport Sınıfı

Giriş
Sınıfın metodları şöyle
public class LockSupport {
  ...
  public static void park() 
  public static void park(Object blocker) 
  public static void parkNanos(long nanos) 
  public static void parkNanos(Object blocker, long nanos) 
  public static void parkUntil(long deadline) 
  public static void parkUntil(Object blocker, long deadline) 
  public static Object getBlocker(Thread t) 
  public static void unpark(Thread thread) 
  ...
}
Ne İçin Kullanılır?
Açıklaması şöyle. Yani Thread'i askıya alma, devam etme vs. gibi işler için kullanılır
these methods are designed to be used as tools for creating higher-level synchronization utilities, and are not in themselves useful for most concurrency control applications.
Açıklaması şöyle. Yani park(), parkNanos(), parkUntil(), unpark() metodları Thread sınıfında deprecate edilen bazı metodlar yerine kullanılabilir.
This class provides a low-level alternative to the deprecated methods Thread.suspend( ) and Thread.resume(). The park(), parkNanos(), and parkUntil() methods suspend, or park, the thread until it is unparked by another thread with unpark(), or until it is interrupted by another thread, or until the specified time elapses.
park metodu - Thread
LockSupport.park() ile thread askıya (suspend) alınır 
Örnek
Şöyle yaparız
@Test
void park() throws InterruptedException {
  Thread secondaryThread = new Thread(LockSupport::park);
 
  secondaryThread.start(); // Thread starts
 
  secondaryThread.join(2000); // Thread is suspended
log.info("Could not join thread is parked"); assertTrue(secondaryThread.isAlive()); // Thread is still alive because it is suspended LockSupport.unpark(secondaryThread); // Resume the thread secondaryThread.join(); assertFalse(secondaryThread.isAlive()); // Thread is not alive anymore log.info("Thread was unparked"); }
parkNanos metodu - nanosecond
LockSupport.parkNanos() bir thread'i çok kısa süreyle uyutmak için kullanılır. 

sleep vs parkNanos
Thread.sleep() milisaniye cinsinde parametre aldığı için en az 1 milisaniye uyuyacaktır. parkNanos() nanosaniye cinsinden parametre aldığı için daha kısa uyuma ihtimali yüksek.
TimeUnit.sleep() altta Thread.sleep() kulandığı için en az 1 milisaniye uyuyacaktır. 
Condition.awaitNanos() altta LockSupport.partkNanos() kullanır. 


Thread Ne Kadar Uyur?
Thread'in kadar uyuyacağı garanti edilmiyor. Belirtilen süre geçinceye veya bir başka thread tarafından unpark() metodu çağrılıncaya kadar thread'i durdurur.  Açıklaması şöyle. Yani parkNanos() erken dönebilir.
parkNanos() parks the thread for the specified number of nanoseconds. parkUntil() parks the thread until the specified time, using the millisecond representation of System.currentTimeMillis(). Any call to these parking methods may return spuriously, so it is important to call park( ) in a loop that can repark the thread if it should not have resumed.

Linux
Linux için açıklaması şöyle. Yani Linux için en az süre 50 mikro saniye ve katı
`LockSupport.parkNanos()` would either return almost immediately or in roughly 50 microseconds steps. In other words: Calling `LockSupport.parkNanos(10000)` would not return after 10 microseconds, but roughly after 50 μs. `LockSupport.parkNanos(55000)` would not return after 55 μs, but roughly after 100 μs, etc. The 50 μs step was present way too consistently to be a coincidence. 
Windows
Windows için süre Linux'tan çok daha uzun. Açıklaması burada

Örnek
Şöyle yaparız. Bu kodda thread gerekiyorsa belirtilen nano saniye kadar uyur
private boolean waitForPermission(final long nanosToWait) {
  waitingThreads.incrementAndGet();
  long deadline = currentNanoTime() + nanosToWait;
  boolean wasInterrupted = false;
  while (currentNanoTime() < deadline && !wasInterrupted) {
    long sleepBlockDuration = deadline - currentNanoTime();
    parkNanos(sleepBlockDuration);
    wasInterrupted = Thread.interrupted();
  }
  waitingThreads.decrementAndGet();
  if (wasInterrupted) {
    currentThread().interrupt();
  }
  return !wasInterrupted;
}
Örnek
Şöyle yaparız
public static void main(String[] args) {
  CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
    System.out.println("started work");
    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
    System.out.println("done work");
    return "a";
  });

  LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
  cf.complete("b");
  System.out.println(cf.join());
}
Örnek
Şöyle yaparız.
static volatile boolean running = true;

public static void main(String[] args) throws IOException {
  
  ...
  Thread thread1 = new Thread(() -> {
    LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(50));
    while(running && !Thread.interrupted()) {
      LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100));
      ...
    }
  });
  thread1.setDaemon(true);
  thread1.start();
  Thread thread2 = new Thread(() -> {
    
    while(running && !Thread.interrupted()) {
      LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100));
      ...
    }
  
  });
  thread2.setDaemon(true);
  thread2.start();
  LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(5));
  thread2.interrupt();
  LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
  running = false;
}

Hiç yorum yok:

Yorum Gönder