zoukankan      html  css  js  c++  java
  • 《图解Java多线程设计模式》之三:Immutable 模式

    一,什么是Immutable模式?
    immutable就是不变的,不发生改变的。Immutable模式中存在着确保实例状态不发生变化改变的类。这些实例不需要互斥处理。
    String就是一个Immutable类,String实例所表示的字符串的内容不会变化。

    二,定义一个使用Immutable模式的类

    public final class Person {
        private final String name;
        private final String address;
    
        public Person(String name,String address){
            this.name = name;
            this.address = address;
        }
        public String getName(){
            return name;
        }
        public String getAddress(){
            return address;
        }
    
        @Override
        public String toString() {
            return "[ Person : name = "+name+",address = "+address+"]";
        }
    }

    final修饰类,无法创建子类,防止子类修改其子段值
    private修饰字段,内部可见,防止子类修改字段值
    final修饰了字段,赋值后不在改变

    三,何时使用这种模式?

    1.实例创建后,状态不再发生变化
    2.实例是共享的,且被频繁访问时

    四,集合类与多线程

    1.ArrayList类用于提供可调整大小的数组,是非线程安全的。当多个线程并发执行读写时,是不安全的。

    public class WriterThread extends Thread {
        private final List<Integer> list;
    
        public WriterThread(List<Integer> list){
            super("WriterThread");
            this.list = list;
        }
    
        @Override
        public void run() {
            for (int i = 0;true ; i++) {
                list.add(i);
                list.remove(0);
            }
        }
    }
    public class ReaderThread extends Thread{
        private final List<Integer> list;
    
        public ReaderThread(List<Integer> list){
            super("ReaderThread");
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true){
           for (int n :list){
             System.out.println(n);
           }
    System.out.println("------"); } } }
    /**
    * 并发读写List,会出异常
    * Exception in thread "ReaderThread" java.util.NoSuchElementException
    * Exception in thread "ReaderThread" java.util.ConcurrentModificationException
    *
    */

    public
    class ListTest { public static void main(String[] args) { List<Integer> list = new ArrayList<>();new WriterThread(list).start(); new ReaderThread(list).start(); } }

    2.利用Collections.synchronizedList方法锁进行的同步

    利用Collections.synchronizedList方法进行同步,就能够得到线程安全的实例

    public class WriterThread extends Thread {
        private final List<Integer> list;
    
        public WriterThread(List<Integer> list){
            super("WriterThread");
            this.list = list;
        }
    
        @Override
        public void run() {
            for (int i = 0;true ; i++) {
                list.add(i);
                list.remove(0);
            }
        }
    }
    public class ReaderThread extends Thread{
        private final List<Integer> list;
    
        public ReaderThread(List<Integer> list){
            super("ReaderThread");
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true){
                //使用了synchronizedList,读数据时必须加锁
                synchronized (list){
                    for (int n :list){
                        System.out.println(n);
                    }
                }
                System.out.println("------");
            }
    
        }
    }
    public class ListTest {
        public static void main(String[] args) {
            List<Integer> arrayList = new ArrayList<>();
            List<Integer> list= Collections.synchronizedList(arrayList);
            new WriterThread(list).start();
            new ReaderThread(list).start();
        }
    }

    3.使用copy-on-write 的java.util.concurrent.CopyOnWriteArrayList类

    copy-on-write,就是写时复制,如果使用copy-on-write,当对集合执行 写操作时,内部已确保安全的数组就会被整体复制。复制之后,就无需在使用迭代器依次读取数据时

    担心元素被修改了。所以该类不会抛出并发修改异常

    public class WriterThread extends Thread {
        private final List<Integer> list;
    
        public WriterThread(List<Integer> list){
            super("WriterThread");
            this.list = list;
        }
    
        @Override
        public void run() {
            for (int i = 0;true ; i++) {
                list.add(i);
                list.remove(0);
            }
        }
    }
    public class ReaderThread extends Thread{
        private final List<Integer> list;
    
        public ReaderThread(List<Integer> list){
            super("ReaderThread");
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true){
          
                for (int n :list){ 
             System.out.println(n); 
           }
                             
                System.out.println("------");
            }
    
        }
    }
    
    
    public class CopyOnWriteListTest {
    public static void main(String[] args) {
    final List<Integer> list = new CopyOnWriteArrayList<>();
    new WriterThread(list).start();
    new ReaderThread(list).start();
    }

    }
     

    使用copy-on-write时,每次执行 写操作时都会执行复制。因此程序频繁执行写操作时,如果使用CopyOnWriteArrayList,会比较花费时间。

    如果写操作比较少,读炒作频繁时,很适合用CopyOnWriteArrayList。

    具体根据情况而定。

  • 相关阅读:
    绿茶一杯辨蜂蜜
    将Windows桌面扩展到第二个显示器/投影机上
    各种茶的特点和挑选(未完)
    转载一位操盘手的惊人语录 
    大家看看这个资料,有助于你了解股市
    庄家的故事之000503海虹控股
    股本变迁,分红扩股数据调查
    onchange 和 onkeyup,onpropertychange 用法小记
    对范美忠事件的评论
    一位天涯的朋友在星期一晚上发来的留言
  • 原文地址:https://www.cnblogs.com/inspred/p/9379326.html
Copyright © 2011-2022 走看看