Which Java Collections are synchronized(thread safe), which are not?

前端 未结 10 2058
礼貌的吻别
礼貌的吻别 2020-12-16 11:05

Which Java Collections are synchronized, which are not?

Example: HashSet is not synchronized

相关标签:
10条回答
  • 2020-12-16 11:58

    import java.util.Collections; //Import this

    List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
    

    This is how you can synchronise a list in java.

    0 讨论(0)
  • 2020-12-16 12:00

    There are three groups of Collections.

    • Java 1.0 collections which mostly legacy classes. This includes Hashtable, Vector, Stack. These are synchronized but I don't recommend you use them. Properties is perhaps one exception, but I wouldn't use it in a multi-threaded context.
    • Java 1.2 collections added in 1998 which largely replaced these collection are not synchronized, but can be synchronized using Collections.synchronizedXxx() methods
    • Java 5.0 concurrency collections added in 2004 support lock free, thread safe collections.

    In short, none of the collections I would recommend you use are synchronized.

    0 讨论(0)
  • 2020-12-16 12:03

    The previous example is totally wrong.

    First of all, you are not accessing from different threads the list that you just synchronized, you have no prove that the synchronization is being performed properly, you cannot prove that the add process is atomic. Second the synchronized clause over the list itself is a bad practice, you don't know if the optimizer will use an item in the list to do the synchronization, leading to an unexpected behavior. Also, what you're synchronizing is the access to the elements in the list read/write, not the list itself. Take out the Collections.synchronized and see the output. Try many times. Please take following example:

    class ProcessSomething {
        private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
        private void calculate() {
            for (int i = 0; i < 10000; i++) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException ex) {
                    Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
                }
                integerList.add(new Random().nextInt(100));
            }
        }
        private void calculate2() {
            for (int i = 0; i < 10000; i++) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException ex) {
                    Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
                }
                integerList.add(new Random().nextInt(100));
            }
        }
        public void process() {
            Long start = System.currentTimeMillis();
            Thread t1 = new Thread(new Runnable() {
                public void run() {
                    calculate();
                }
            });
            t1.start();
            Thread t2 = new Thread(new Runnable() {
                public void run() {
                    calculate2();
                }
            });
            t2.start();
            try {
                t1.join();
                t2.join();
            } catch (InterruptedException ex) {
                Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
            }
            Long end = System.currentTimeMillis();
            System.out.println("Duration: " + (end - start));
            System.out.println("List size: " + integerList.size());
        }
    }
    public class App {
        public static void main(String[] args) {
            new ProcessSomething().process();
        }
    }
    
    0 讨论(0)
  • 2020-12-16 12:04

    synchronize makes performance lower. of course, Java collection is not synchronized. but Java provides a Synchronization Wrappers to synchronize Java Collection see link

    for example:
    
    
        import java.util.ArrayList;
        import java.util.Collections;
        import java.util.Iterator;
        import java.util.List;
    
        public class SynchronizedListExample {
    
            public static void main(String[] args) {
    
                List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
    
                syncList.add("one");//no need to synchronize here
                syncList.add("two");
                syncList.add("three");
                String st = syncList.get(0); //it is ok here => no need to synchronize
    
                // when iterating over a synchronized list, we need to synchronize access to the synchronized list
               //because if you don't synchronize here, synchList maybe be changed during iterating over it
                synchronized (syncList) {
                    Iterator<String> iterator = syncList.iterator();
                    while (iterator.hasNext()) {
                        System.out.println("item: " + iterator.next());
                    }
                }
    
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题