2016-07-13 13 views
8

Jeśli iterator z funkcją fail-safe tworzy oddzielną kopię i pracuje nad tym, jak to możliwe, że zdaje sobie sprawę z jakichkolwiek zmian dokonanych w oryginale?Jaka jest logika iteratora fail-safe?

public class concurrentHashMap { 
    public static void main(String[] args) throws InterruptedException { 
     MapCheck obj1 = new MapCheck(); 
     Thread t1 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       obj1.put(); 
      } 
     }); 

     Thread t2 = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       obj1.iterte(); 
      } 
     }); 

     t1.start(); 
     t2.start(); 
     t1.join(); 
     t2.join(); 
    } 
} 

class MapCheck { 
    Map<Integer,String> map = new ConcurrentHashMap<>(); 
    { 
     map.put(1, "pujan"); 
     map.put(2, "manish"); 
     map.put(3, "swati"); 
    } 

    void iterte() throws InterruptedException { 
     for (int key : map.keySet()) { 
      Thread.sleep(2000); 
      System.out.println(map.get(key)); 
     } 
    } 

    void put() throws InterruptedException{ 
     Thread.sleep(2000); 
     map.put(1, "pujan1"); 
     map.put(2, "manish1"); 
     map.put(3, "swati1"); 
    } 
} 

Wyjście jest:

pujan1 
manish1 
swati1 

Odpowiedz

12

Nie ma czegoś takiego jak iterator "fail-safe" w Javie. Przynajmniej specyfikacje Java SE nie definiują takiego pojęcia. Dlatego zalecam, aby nie używać terminu "fail-safe" do opisu iteratorów Java.

Jestem świadomy, że różne artykuły w Internecie i innych miejscach na stosie przepełnienia stosu używają terminu "fail-safe", ale ich użycie nie jest definitywne i prawdopodobnie będzie nieprawidłowe lub co najmniej mylące. Wierzę, że została wprowadzona w błąd przez taką dokumentację.

Wygląda na to, że czytasz gdzieś, że iterator "fail-safe" działa na oddzielnej kopii. W twoim przykładzie używasz ConcurrentHashMap, który rzeczywiście ma iteratory, które nie są odporne na awarie. Jednak iteratory CHM nie działają na kopii. Zamiast tego mają semantykę opisaną przez oficjalną specyfikację jako weakly consistent. Definicja jest nieco zawiłe, ale w zasadzie każdy element zgłaszany przez taki iterator jest zagwarantowany w pewnym momencie w kolekcji. Tego rodzaju iteratory mogą lub nie mogą odzwierciedlać zmian w kolekcji, które zostały wykonane po rozpoczęciu iteracji. Dlatego wątek, który uruchamia iterator, widzi zmiany wprowadzone przez drugi wątek. (Jest również możliwe, aby niektóre lub wszystkie zmiany były widoczne, ponieważ wątki te mają wyścig danych.)

Przykład innej kolekcji, której iteratory nie są odporne na awarie, to CopyOnWriteArrayList. Iteratory tej kolekcji działają na migawce, więc wszelkie późniejsze zmiany w kolekcji są nigdy widoczne za pośrednictwem iteratora.

Dla kompletności, tutaj jest definicja iteratora fail-fast ze specyfikacji . Większość innych (nie współbieżnych) kolekcji w Javie ma awaryjną politykę iteracji, która jest zdefiniowana podobnie.