2016-07-13 74 views
8

Se iteratore fail-safe crea una copia separata e ci lavora, come mai è a conoscenza di eventuali modifiche apportate all'originale?Qual è la logica di un iteratore 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"); 
    } 
} 

L'output è:

pujan1 
manish1 
swati1 

risposta

12

Non c'è cosa come un iteratore "fail-safe" in Java. Almeno, le specifiche di Java SE non definiscono un termine del genere. Pertanto ti consiglio di evitare di usare il termine "fail-safe" per descrivere gli iteratori Java.

Sono ben consapevole del fatto che vari articoli su Internet e altrove su Stack Overflow utilizzano il termine "fail-safe", ma il loro utilizzo non è definitivo, ed è probabile che sia errato o quantomeno fuorviante. Credo che tu sia stato ingannato da tale documentazione.

Sembra che tu abbia letto da qualche parte che un iteratore "fail-safe" funziona su una copia separata. Nel tuo esempio, usi uno ConcurrentHashMap, che in effetti ha iteratori che non sono fail-fast. Tuttavia, gli iteratori di CHM non funzionano su una copia. Invece, hanno semantica descritta dalla specifica ufficiale come weakly consistent. La definizione è alquanto astrusa, ma in sostanza, qualsiasi elemento riportato da tale iteratore è garantito che sia esistito nella raccolta ad un certo punto nel tempo. Questo tipo di iteratori potrebbe o potrebbe non riflettere le modifiche alla raccolta che sono state fatte dopo l'iterazione avviata. Ecco perché il thread che esegue l'iteratore vede le modifiche apportate dall'altro thread. (È anche possibile che alcune o nessuna delle modifiche siano visibili, poiché questi thread hanno una corsa di dati.)

Un esempio di un'altra raccolta i cui iteratori non sono fail-fast è CopyOnWriteArrayList. Gli iteratori di questa raccolta operano su un'istantanea, quindi qualsiasi successiva modifica alla raccolta è mai visibile tramite un iteratore.

Per completezza, ecco la definizione di un iteratore fail-fast dalla specifica ArrayList. La maggior parte delle altre raccolte (non concorrenti) in Java hanno una politica di iterazione fail-fast definita in modo simile.