1. 程式人生 > 實用技巧 >[轉]MyBatis - MyBatis使用log4j2顯示sql和結果集

[轉]MyBatis - MyBatis使用log4j2顯示sql和結果集

執行緒安全的集合

  • CopyOnWriteArrayList
    • 執行緒安全的ArrayList,加強版的讀寫分離。
    • 寫有鎖,讀無鎖,讀寫之間不阻塞,由於讀寫鎖
    • 寫入時,先copy一個容器副本、再新增新元素,最後替換引用。(浪費空間
    • 使用方式與ArrayList無異。
package com.sun.base.XianCheng;

import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用多執行緒操作CopyOnWriteArrayList
 */
public class Mylist {
    public static void main(String[] args) {
        //建立集合
        List<String> list=new CopyOnWriteArrayList<>();
        //建立執行緒池
        ExecutorService es = Executors.newFixedThreadPool(5);
        //提交任務
        for (int i=0;i<5;i++){
            es.submit(new Runnable() {
                @Override
                public void run() {
                    for (int j =0;j<10;j++){
                        list.add(Thread.currentThread().getName()+"---"+new Random().nextInt(1000));
                    }
                }
            });
        }
        //關閉執行緒池
        es.shutdown();
        while (!es.isTerminated()){}
        //列印結果
        System.out.println(list.size());
        for (String str:list) {
            System.out.println(str.toString());
        }
    }

}
  • CopyOnWriteArraySet
    • 執行緒安全的Set,底層使用CopyOnWriteArrayList實現。
    • 唯一不同在於,使用addIfAbsent()新增元素,會遍歷陣列,如存在元素,則不新增(扔掉副本)。
    • 重複依據:equals方法。
package com.sun.base.XianCheng;
import java.util.concurrent.CopyOnWriteArraySet;
/**
 * 演示CopyOnWriteArraySet
 */
public class MySet {
    public static void main(String[] args) {
        //建立集合
        CopyOnWriteArraySet<String> strings = new CopyOnWriteArraySet<>();
        //新增元素
        strings.add("aaa");
        strings.add("bbb");
        strings.add("ccc");
        strings.add("ddd");
        strings.add("aaa");
        //列印
        System.out.println("元素個數:"+strings.size());
        System.out.println(strings.toString());//有序
    }
}

Queue介面(佇列)

  • Collection的子介面,表示佇列FIFO(先進先出)

  • 常見方法:

    • 丟擲異常:
      • boolean add(E e)//順序新增一個元素(到達上限後,再新增則會丟擲異常)
      • E remove()//獲得第一個元素並移除(如果佇列沒有元素時,則丟擲異常)
      • E element()//獲得第一個元素但不移除(如果佇列沒有元素時,則會丟擲異常)
    • 返回特殊值:推薦使用
      • boolean offer(E e)//順序新增一個元素(到達上限後,再新增則會返回false)
      • E poll()//獲得第一個元素並移除(如果佇列沒有元素時,則返回null)
      • E peek()//獲得第一個元素但不移除(如果佇列沒有元素時,則返回null)
  • ConcurrentLinkedQueue

    • 執行緒安全、可高效讀寫的佇列,高併發下效能最好的佇列。
    • 無鎖、CAS比較交換演算法,修改的方法包含三個核心引數(V,E,N)
    • V:要更新的變數;E:預期值;N:新值。
    • 只有當VE時,VN;否則表示已被更新過,則取消當前操作。
package com.sun.base.XianCheng;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
 * ConcurrentLinkedQueue的使用
 */
public class MyConcurrentLinkedQueue {
    public static void main(String[] args) throws InterruptedException {
        //建立安全佇列
        ConcurrentLinkedQueue<Integer> integers = new ConcurrentLinkedQueue<>();
        //建立執行緒
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <= 5; i++) {
                    integers.offer(i);
                }
            }
        });
        Thread thread1=new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 6; i <= 10; i++) {
                    integers.offer(i);
                }
            }
        });
        //啟動執行緒
        thread.start();
        thread1.start();
        thread.join();
        thread1.join();
        //出隊
        int size=integers.size();
        for (int i=0;i<size;i++){
            System.out.println(integers.poll());
        }
    }
}
  • BlockingQueue介面(阻塞佇列)

    • Queue的子介面,阻塞的佇列,增加了兩個執行緒狀態為無限期等待的方法。

    • 方法:

      • void put(E,e) //將指定的元素插入次佇列中,如果沒有可用空間,則等待。
      • E take() //獲取並移除次佇列頭部元素,如果沒有可用元素,則等待。
    • 可用於解決生產者、消費者問題。

    • 實現類

      • ArrayBlockingQueue:陣列結構實現,有界佇列。(手工固定上限)

        package com.sun.base.XianCheng;
        
        import java.util.concurrent.ArrayBlockingQueue;
        
        /**
         * 阻塞佇列的使用
         * 案例1:實現生產者和消費者
         */
        public class MyBlockingQueue {
            public static void main(String[] args) throws InterruptedException {
                //建立一個有界佇列
                ArrayBlockingQueue<Integer> strings = new ArrayBlockingQueue<>(6);//固定麵包上限為6
                //建立兩個執行緒
                Thread t1=new Thread(new Runnable() {
                    @Override
                    public  void  run() {
                        for (int i=1;i<20;i++){
                            try {
                                strings.put(i);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+"生產了第"+i+"號麵包");
                        }
                    }
                },"小明");
                Thread t2=new Thread(new Runnable() {
                    @Override
                    public  void run() {
                        for (int i=1;i<20;i++){
                            try {
                                strings.take();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+"消費了第"+i+"號麵包");
                        }
                    }
                },"小紅");
                t1.start();
                t2.start();
            }
        }
        
      • LinkedBlockingQueue:連結串列結構實現,有界佇列。(預設上限Integer.MAX_VALUE)

  • ConcurrentHashMap

    • 初始容量預設為16段(Segment),使用分段鎖設計。
    • 不對整個Map加鎖,而是為每個Segment加鎖。
    • 當多個物件存入同一個Segment時,才需要互斥。
    • 最理想狀態為16個物件分別存入16個Segment,並行數量16。
    • 使用方式與HashMap無異。
package com.sun.base.XianCheng;

import java.util.concurrent.ConcurrentHashMap;

/**
 * ConcurrentHashMap的使用
 */
public class MyConcurrentHashMap {
    public static void main(String[] args) {
        //建立集合
        ConcurrentHashMap<String, String> hashMap = new ConcurrentHashMap<>();
        //使用多執行緒新增資料
        for (int i=0;i<5;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<4;j++){
                        hashMap.put(Thread.currentThread().getName()+"---"+j,j+"  ");
                        System.out.println(hashMap);
                    }

                }
            }).start();
        }
    }
}