1. 程式人生 > >java多執行緒總結-同步容器與併發容器的對比與介紹

java多執行緒總結-同步容器與併發容器的對比與介紹

目錄

  • 1 容器集簡單介紹
  • 2 同步容器
  • 3 併發容器
  • 4 案例講解
    • 4.1 Map/Set
    • 4.2 List
    • 4.3 Queue
      • 4.3.1 ConcurrentLinkedQueue
      • 4.3.2 阻塞佇列LinkedBlockingQueue
      • 4.3.3 BlockingQueue
      • 4.3.4 延時佇列DelayQueue
      • 4.3.5 轉移佇列LinkedTransferQueue
      • 4.3.6 SynchronousQueue

1 容器集簡單介紹

java.util包下面的容器集主要有兩種,一種是Collection介面下面的List和Set,一種是Map,
大致結構如下:

  • Collection
    • List
      • LinkedList
      • ArrayList
      • Vector
        • Stack
    • Set
      • HashSet
      • TreeSet
      • LinkedSet
  • Map
    • Hashtable
    • HashMap
    • WeakHashMap

2 同步容器

同步容器也叫執行緒安全容器,是通過syncrhoized關鍵字對執行緒不安全的操作進行加鎖來保證執行緒安全的

其中同步容器主要包括:
1.Vector、Stack、HashTable
2.Collections 工具類中提供的同步集合類
Collections類是一個工具類,相當於Arrays類對於Array的支援,Collections類中提供了大量對集合或者容器進行排序、查詢的方法。它還提供了幾個靜態方法來建立同步容器類:

3 併發容器

java.util.concurrent提供了多種執行緒安全容器,大多數是使用系統底層技術實現的執行緒安全,也叫併發容器,類似native。Java8中使用CAS。

4 案例講解

這裡主要介紹一些常見的同步容器和併發容器,通過案例輸出結果對比進行介紹
我大致分為了三類Map/Set,List,Queue來進行講解,但一個Map/Set,只介紹了Map,因為在java的設計中,Set就是Map,說白了就是隻有Key沒有Value的Map,好了,現在開始進入正題

4.1 Map/Set

程式碼中new了三個Map,HashTable,ConcurrentHashMap,ConcurrentSkipListMap比較每個map的執行效率,起100個執行緒向map中存放10000條隨機數,並通過門閂CountDownLatch控制執行狀態,輸出執行時間

/**
 * 併發容器 - ConcurrentMap
 */
package com.bernardlowe.concurrent.t06;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CountDownLatch;

public class Test_01_ConcurrentMap {
    
    public static void main(String[] args) {
        final Map<String, String> map = new Hashtable<>();
        // final Map<String, String> map = new ConcurrentHashMap<>();
        // final Map<String, String> map = new ConcurrentSkipListMap<>();
        final Random r = new Random();
        Thread[] array = new Thread[100];
        final CountDownLatch latch = new CountDownLatch(array.length);
        
        long begin = System.currentTimeMillis();
        for(int i = 0; i < array.length; i++){
            array[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int j = 0; j < 10000; j++){
                        map.put("key"+r.nextInt(100000000), "value"+r.nextInt(100000));
                    }
                    latch.countDown();
                }
            });
        }
        for(Thread t : array){
            t.start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("執行時間為 : " + (end-begin) + "毫秒!");
    }

}

Hashtable結果:

ConcurrentHashMap結果:

ConcurrentSkipListMap結果:

ConcurrentHashMap的底層是雜湊實現的同步Map(Set)
ConcurrentSkipListMap內部是SkipList(跳錶)結構實現的非阻塞讀/寫/刪除 的 Map,它的value是有序儲存的, 而且其內部是由縱橫連結串列組成,在JDK1.8中,ConcurrentHashMap的效能和儲存空間要優於ConcurrentSkipListMap

為了讓測試資料結果對比更加直觀,我這裡故意將生成的隨機數調的比較大。這裡需要注意一下,在測試的時候,如果機器效能比較好,可能結果會出現誤差,因為System.currentTimeMillis(),這個方法呼叫了個native方法,獲取的時間精度會依賴於作業系統的實現機制,具體為什麼,可以看看這篇文章http://blog.sina.com.cn/s/blog_6b8bd9d80101fe8t.html。但我按照文件的辦法將System.currentTimeMillis()改為System.nanoTime(),發現並沒有解決這個問題,可能是因為並沒有達到納秒級別吧。

4.2 List

下面程式碼與4.1的程式碼類似,也是new了三個List,ArrayList,Vector,CopyOnWriteArrayList,起100個執行緒向map中存放1000條隨機數,並通過門閂CountDownLatch控制執行狀態,輸出執行時間和最後list的的長度。由於ArrayList是執行緒不安全,在多執行緒執行的時候,需要try{}catch{},否則會因為陣列越界而報錯,因為ArrayList底層是一個長度動態擴充套件的陣列

/**
 * 併發容器 - CopyOnWriteList
 */
package com.bernardlowe.concurrent.t06;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;

public class Test_02_CopyOnWriteList {
    
    public static void main(String[] args) {
         final List<String> list = new ArrayList<String>(); // 執行緒不安全
//       final List<String> list = new Vector<>(); // 執行緒安全
//      final List<String> list = new CopyOnWriteArrayList<>(); // 執行緒安全
        final Random r = new Random();
        Thread[] array = new Thread[100];
        final CountDownLatch latch = new CountDownLatch(array.length);
        
        long begin = System.currentTimeMillis();
        for(int i = 0; i < array.length; i++){
            array[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int j = 0; j < 1000; j++){
                        try {
                            list.add("value" + r.nextInt(100000));
                        } catch (Exception e) {

                        }
                    }
                    latch.countDown();
                }
            });
        }
        for(Thread t : array){
            t.start();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("執行時間為 : " + (end-begin) + "毫秒!");
        System.out.println("List.size() : " + list.size());
    }

}

ArrayList結果:因為ArrayList是執行緒不安全的,所以在多執行緒環境中,可能會丟失資料

Vector結果:

CopyOnWriteArrayList結果:

CopyOnWriteArrayList是讀寫分離的,寫時複製出一個新的陣列,完成插入、修改或者移除操作後將新陣列賦值給array,讀取時直接讀取最新的陣列,所以在寫操作時,效率非常低(雖然寫比較慢,但它在刪除陣列頭和尾還是很快的)
從上面三個結果可以看出,CopyOnWriteArrayList雖然保證了執行緒安全,但它的寫操作效率太低了,但相比Vector,併發安全且效能比Vector好,Vector是增刪改查方法都加了synchronized,保證同步,但是每個方法執行的時候都要去獲得鎖,效能就會大大下降,而CopyOnWriteArrayList 只是在增刪改上加鎖,但是讀不加鎖,在讀方面的效能就好於Vector,CopyOnWriteArrayList支援讀多寫少的併發情況,所以CopyOnWriteArrayList是不會存在髒讀問題的

4.3 Queue

這一節主要介紹一些併發佇列的常用api

4.3.1 ConcurrentLinkedQueue

基礎連結串列同步佇列

peek() -> 檢視queue中的首資料
poll() -> 獲取queue中的首資料

/**
 * 併發容器 - ConcurrentLinkedQueue
 *  佇列 - 連結串列實現的。 
 */
package com.bernardlowe.concurrent.t06;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Test_03_ConcurrentLinkedQueue {
    
    public static void main(String[] args) {
        Queue<String> queue = new ConcurrentLinkedQueue<>();

        //向佇列中增加10個數據
        for(int i = 0; i < 10; i++){
            queue.offer("value" + i);
        }
        
        System.out.println(queue);
        System.out.println(queue.size());

        // peek() -> 檢視queue中的首資料,
        System.out.println("首資料 " + queue.peek());
        System.out.println("佇列長度 "+ queue.size());
        System.out.println("===================");
        // poll() -> 獲取queue中的首資料
        System.out.println("首資料 " + queue.peek());
        System.out.println("佇列長度 "+ queue.size());
    }

}

結果:

4.3.2 阻塞佇列LinkedBlockingQueue

阻塞佇列,佇列容量不足自動阻塞,佇列容量為0自動阻塞。

put & take - 自動阻塞
put自動阻塞, 佇列容量滿後,自動阻塞
take自動阻塞方法, 佇列容量為0後,自動阻塞

/**
 * 併發容器 - LinkedBlockingQueue
 *  阻塞容器。
 */
package com.bernardlowe.concurrent.t06;

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class Test_04_LinkedBlockingQueue {
    
    final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
    final Random r = new Random();
    
    public static void main(String[] args) {
        final Test_04_LinkedBlockingQueue t = new Test_04_LinkedBlockingQueue();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        t.queue.put("value"+t.r.nextInt(1000));
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }, "producer").start();
        
        for(int i = 0; i < 3; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        try {
                            System.out.println(Thread.currentThread().getName() + 
                                    " - " + t.queue.take());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "consumer"+i).start();
        }
    }

}

結果:

結果就是一個簡單的生產者消費者

4.3.3 BlockingQueue

底層陣列實現的有界佇列,當容量不足的時候,有阻塞能力,根據呼叫API(add/put/offer)不同,有不同特性
這裡主要介紹三個api方法add,put,offer

  • add方法在容量不足的時候,丟擲異常。
  • put方法在容量不足的時候,阻塞等待。
  • offer方法

    單引數offer方法,不阻塞。容量不足的時候,返回false。當前新增資料操作放棄。
    三引數offer方法(offer(value,times,timeunit)),容量不足的時候,阻塞times時長(單位為timeunit),如果在阻塞時長內,有容量空閒,新增資料返回true。如果阻塞時長範圍內,無容量空閒,放棄新增資料,返回false。

/**
 * 併發容器 - ArrayBlockingQueue
 *  有界容器。
 */
package com.bernardlowe.concurrent.t06;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class Test_05_ArrayBlockingQueue {
    
    final BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
    
    public static void main(String[] args) {
        final Test_05_ArrayBlockingQueue t = new Test_05_ArrayBlockingQueue();
        
        for(int i = 0; i < 5; i++){

            // 1.add method
            System.out.println("add method : " + t.queue.add("value"+i));

            // 2.put method
//          try {
//              t.queue.put("put"+i);
//          } catch (InterruptedException e) {
//              e.printStackTrace();
//          }
//          System.out.println("put method : " + i);

            // 3.offer method
//          System.out.println("offer method : " + t.queue.offer("value"+i));
//          try {
//              System.out.println("offer method : " +
//                          t.queue.offer("value"+i, 1, TimeUnit.SECONDS));
//          } catch (InterruptedException e) {
//              e.printStackTrace();
//          }
        }
        
        System.out.println(t.queue);
    }

}

add方法結果:容量不足的時候,丟擲異常

put方法結果:容量不足的時候,阻塞等待

單/多引數offer方法結果:


單引數offer:容量不足,直接返回結果,不阻塞
多引數offer:容量不足,阻塞

4.3.4 延時佇列DelayQueue

延時佇列。根據比較機制,實現自定義處理順序的佇列。常用於定時任務。
如:定時關機。
具體示例程式碼如下

/**
 * 併發容器 - DelayQueue
 */
package com.bernardlowe.concurrent.t06;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class Test_06_DelayQueue {
    
    static BlockingQueue<MyTask_06> queue = new DelayQueue<>();
    
    public static void main(String[] args) throws InterruptedException {
        long value = System.currentTimeMillis();
        MyTask_06 task1 = new MyTask_06(value + 2000);
        MyTask_06 task2 = new MyTask_06(value + 1000);
        MyTask_06 task3 = new MyTask_06(value + 3000);
        MyTask_06 task4 = new MyTask_06(value + 2500);
        MyTask_06 task5 = new MyTask_06(value + 1500);
        
        queue.put(task1);
        queue.put(task2);
        queue.put(task3);
        queue.put(task4);
        queue.put(task5);
        
        System.out.println(queue);
        System.out.println(value);
        for(int i = 0; i < 5; i++){
            System.out.println(queue.take());
        }
    }

}

class MyTask_06 implements Delayed {
    
    private long compareValue;
    
    public MyTask_06(long compareValue){
        this.compareValue = compareValue;
    }

    /**
     * 比較大小。自動實現升序
     * 建議和getDelay方法配合完成。
     * 如果在DelayQueue是需要按時間完成的計劃任務,必須配合getDelay方法完成。
     */
    @Override
    public int compareTo(Delayed o) {
        return (int)(this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }

    /**
     * 獲取計劃時長的方法。
     * 根據引數TimeUnit來決定,如何返回結果值。
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(compareValue - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
    
    @Override
    public String toString(){
        return "Task compare value is : " + this.compareValue;
    }
    
}

結果:

4.3.5 轉移佇列LinkedTransferQueue

這裡主要是兩個方法的區別,add和transfer

  • add - 佇列會儲存資料,不做阻塞等待。
  • transfer - 是TransferQueue的特有方法。必須有消費者(take()方法的呼叫者)。
/**
 * 併發容器 - LinkedTransferQueue
 *  轉移佇列
 */
package com.bernardlowe.concurrent.t06;

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TransferQueue;

public class Test_07_TransferQueue {
    
    TransferQueue<String> queue = new LinkedTransferQueue<>();
    
    public static void main(String[] args) {
        final Test_07_TransferQueue t = new Test_07_TransferQueue();
        
        /*new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + " thread begin " );
                    System.out.println(Thread.currentThread().getName() + " - " + t.queue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "output thread").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            t.queue.transfer("test string");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    t.queue.transfer("test string");
                    // t.queue.add("test string");
                    System.out.println("add ok");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + " thread begin " );
                    System.out.println(Thread.currentThread().getName() + " - " + t.queue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "output thread").start();
        
    }

}

這裡的transfer()和take()都是阻塞方法,take先請求接收資料或者transfer先發送資料,都會進行阻塞等待。
舉個例子,transfer()就相當與手機打電話,當A給B打電話,B必須接收到電話訊號接聽才能進行通話,否則A會一直等待
add()就相當於A給B發簡訊,簡訊已經存到了運營商那邊,等待B接收,不管發簡訊時B是否線上

4.3.6 SynchronousQueue

該佇列一個容量為0的佇列,是一個特殊的TransferQueue,它和TransferQueue很像,但這個佇列必須要有消費執行緒才行
又兩個方法add,put
add方法,無阻塞。若沒有消費執行緒阻塞等待資料,則丟擲異常。
put方法,有阻塞。若沒有消費執行緒阻塞等待資料,則阻塞。

/**
 * 併發容器 - SynchronousQueue
 */
package com.bernardlowe.concurrent.t06;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

public class Test_08_SynchronusQueue {
    
    BlockingQueue<String> queue = new SynchronousQueue<>();
    
    public static void main(String[] args) {
        final Test_08_SynchronusQueue t = new Test_08_SynchronusQueue();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + " thread begin " );
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " - " + t.queue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "output thread").start();
        
        /*try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        // t.queue.add("test add");
        try {
            t.queue.put("test put");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println(Thread.currentThread().getName() + " queue size : " + t.queue.size());
    }

}

t.queue.add("test add");的註釋開啟,t.queue.put("test put");加上註釋
add方法異常結果: 因為它是一個容量為0的佇列

相關推薦

java執行總結-同步容器併發容器對比介紹

目錄 1 容器集簡單介紹 2 同步容器 3 併發容器 4 案例講解 4.1 Map/Set 4.2 List 4.3 Queue 4.3.1 C

js單執行java執行同步非同步

       寫這篇部落格源於想對比一下單執行緒js和多執行緒java兩種語言的區別。       定義區:            單執行緒:只能執行一個任務,只有在完成執行後,才能繼續執行其他的任務。            多執行緒:有多個執行緒,可以同時執行多個任務。

最全java執行總結2--如何進行執行同步

  上篇對執行緒的一些基礎知識做了總結,本篇來對多執行緒程式設計中最重要,也是最麻煩的一個部分——同步,來做個總結。   建立執行緒並不難,難的是如何讓多個執行緒能夠良好的協作執行,大部分需要多執行緒處理的事情都不是完全獨立的,大都涉及到資料的共享,本篇是對執行緒同步的一個總結,如有紕漏的地方,歡迎在評論中指

Java執行學習筆記21之單例模式執行

詳細程式碼見:github程式碼地址   第六章 單例模式與多執行緒 前言: 我之前已經開設了23個設計模式這個專欄,介紹了很多的Java設計模式,其中一些模式對於絕 大多數程式語言設計思想都是類似的,需要了解單例模式的可以去看看。 我們在實際開發中經常用到單例模式,但

Java學習筆記(一) Java執行 synchronized同步方法

1.提出問題-例項變數非執行緒安全 如果多個執行緒同時訪問1個物件的例項變數,則可能出現"非執行緒安全"問題。 1.1 何為非執行緒安全? 我的理解是多個執行緒對一個例項變數操作會出現值被更改,不同步的情況。 1.2 舉例 1.2.1 有私有變數的類HasPr

Java學習筆記(二) Java執行 synchronized同步方法-防止髒讀

1. 髒讀 在給一個物件賦值的時候進行了同步, 但是在取值的時候可能出現意外,此值已經被其他執行緒修改了,這種情況就是髒讀 1.1 PublicVar類 public class PublicVar { public String userName =

Java執行同步機制(synchronized)

原文地址 一段synchronized的程式碼被一個執行緒執行之前,他要先拿到執行這段程式碼的許可權,在 java裡邊就是拿到某個同步物件的鎖(一個物件只有一把鎖); 如果這個時候同步物件的鎖被其他執行緒拿走了,他(這個執行緒)就只能等了(執行緒阻塞在鎖池 等待佇列中)。 取到鎖後,他就開始執行同步程式碼

Java執行總結執行安全佇列Queue

在Java多執行緒應用中,佇列的使用率很高,多數生產消費模型的首選資料結構就是佇列。Java提供的執行緒安全的Queue可以分為阻塞佇列和非阻塞佇列,其中阻塞佇列的典型例子是BlockingQueue,非阻塞佇列的典型例子是ConcurrentLinkedQueue,在實際

java執行同步鎖(Lock)

      從Java5開始,提供了Lock, Lock提供了比synchronized方法和synchronized程式碼塊更廣泛的鎖定操作,Lock可以實現更靈活的結構,並且支援多個相關的Condition物件(物件監視器)。       Lock是控制多個執行緒對共享

java執行解決同步問題的幾種方式、原理和程式碼

生產者類: publicclassProducerextendsThread{// 每次生產的產品數量privateint num;// 所在放置的倉庫privateStorage storage;// 建構函式,設定倉庫publicProducer(Storage storage){this.stora

java執行同步計數器

同步計數器之--CountDownLatch    使用場景:當用戶上傳檔案,我們可以多開幾個執行緒來上傳檔案,當所有的執行緒上傳完成後,檔案才算上傳完成,在此場景下可以使用CountDownLatch,當每個執行緒上傳完成,呼叫CountDownLatch.countDow

java 執行 總結 案例

學完東西后,要學會總結,學會記錄筆記,這樣才會有更大的收穫 首先我們瞭解執行緒和程序的基本概念 一、概念(程式 程序 執行緒) 1、程式:指令集 靜態概念 2、程序:作業系統 排程程式 動態概念 3:執行緒:在程序內多條執行路徑 真正的多執行緒是指多個cpu 二、建立

Java執行同步非同步及阻塞和非阻塞

1、程序和執行緒的概念 程序:執行中的應用程式稱為程序,擁有系統資源(cpu、記憶體) 執行緒:程序中的一段程式碼,一個程序中可以有多段程式碼。本身不擁有資源(共享所在程序的資源); 在java中,程式入口被自動建立為主執行緒,在主執行緒中可以建立多個子執

Java執行總結(6)— 執行池的基本使用和執行流程分析

1 執行緒池的實現原理及基本類結構   合理利用執行緒池能夠帶來三個好處。 降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。 提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。 提高執行緒的可管理性。執行緒是稀缺

java執行總結(處精摘,面試總結)

      用多執行緒只有一個目的,那就是更好的利用cpu的資源,因為所有的多執行緒程式碼都可以用單執行緒來實現。說這個話其實只有一半對,因為反應“多角色”的程式程式碼,最起碼每個角色要給他一個執行緒吧,否則連實際場景都無法模擬,當然也沒法說能用單執行緒來實現:比如最常見

最全java執行總結3——瞭解阻塞佇列和執行安全集合不

  看了前兩篇你肯定已經理解了 java 併發程式設計的低層構建。然而,在實際程式設計中,應該經可能的遠離低層結構,畢竟太底層的東西用起來是比較容易出錯的,特別是併發程式設計,既難以除錯,也難以發現問題,我們還是使用由併發處理的專業人員實現的較高層次的結構要方便、安全得多。 阻塞佇列   對於許多執行緒問題,

java執行總結(系列一)

1、Java中的Thread建立和狀態 (1)新建(New) 建立後尚未啟動。ex:Thread t = new Thread(){//重寫run方法}; (2)可執行(Runnable) 可能正在執行,也可能正在等待 CPU 時間片。包含了作業系統執行緒狀態中的 Running 和 Ready。 (

Java執行之併發包,併發佇列

目錄 1 併發包 2 併發佇列 1 併發包 1.1同步容器類 1.1.1Vector與ArrayList區別 1.1.1.1 ArrayList是最常用的List實現類,內部是通過陣列實現的,它允許對

Java執行——物件及變數的併發訪問

Java多線系列文章是Java多執行緒的詳解介紹,對多執行緒還不熟悉的同學可以先去看一下我的這篇部落格Java基礎系列3:多執行緒超詳細總結,這篇部落格從巨集觀層面介紹了多執行緒的整體概況,接下來的幾篇文章是對多執行緒的深入剖析。   本篇文章主要介紹Java多執行緒中的同步,也就是如何在Java語

Java執行學習總結(Join)

join()方法的用法: join()是主執行緒 等待子執行緒的終止。也就是在子執行緒呼叫了 join() 方法後面的程式碼,只有等到子執行緒結束了才能執行。 例子如下: Java程式碼 p