上一篇python併發中講到了,使用多進程,多線程,多任務來加快程序的運行。其中講到的一點彷佛有點問題,操做系統中線程是調度器的最小執行單位,那爲什麼python中的多線程沒法利用多核,只能在一個處理器上運行呢?由於python中有GIL(全局解釋器鎖)這麼個東西,固然它只是cpython解釋器的一個特性,其餘解釋器可能沒有。java
大學時總在想,學操做系統、計算機組成原理、數據結構有啥用啊?還不如學習如何使用hibernate
、struts
、spring
。當你工做3年後,對如何使用這些工具再也提不起興趣時或者想深刻了解它到底爲何是那樣時,你就會從新回過頭來打量大學時學的這些底層知識。python
也許你對下面一句話耳熟能詳:spring
進程是資源分配的最小單位,線程是最小執行單位。數據結構
大學時讀的徹底是字面意思啊?並無思考什麼是進程,爲什麼要搞出來個進程?好吧,下面又是我杜撰的。多線程
進程是一個操做系統級別的概念,運行一個程序時每每須要各類資源,操做系統把一個程序以及運行時所須要的資源抽象成一個進程,這裏的資源是存儲資源和計算資源。各個進程的計算資源是由操做系統的調度器統一分配的,而不是一個進程永遠霸佔計算資源;由於進程使用的是虛擬內存地址,不一樣進程的同一虛擬地址可能映射到了不一樣的物理內存上,因此不一樣進程間的存儲資源是不共享的。併發
由於進程的儲存資源不共享,建立銷燬和切換的開銷比較大。因此出現了輕量級進程,即線程。線程是共享同一進程的存儲資源的,一個進程能夠建立若干線程。同時它也是調度器的最小執行單元,可見多線程是能利用多核處理器的。工具
java沒有操做進程併發的類,官方暫時也不支持協程,可是有一些第三方庫,比Quasar。下面是多線程的幾種方式:學習
ThreadPoolExecutor
CompletableFuture
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.*; import java.util.stream.IntStream; public class ThreadPoolDemo { static String content = "1234567890abcdefghijklmnopqrstuvwxyz"; static int size = 400; public static void a(){ int cnt = Runtime.getRuntime().availableProcessors() * 2 + 1; ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(cnt); ArrayList<Future<?>> fs = new ArrayList<>(size); long start = System.currentTimeMillis(); for(int i = 0; i < size; ++i){ int seq = i; Future<?> f = threadPoolExecutor.submit(() -> createFile("a", seq)); fs.add(f); } for(Future<?> f : fs){ try { f.get(); } catch (InterruptedException|ExecutionException e) { e.printStackTrace(); } } System.out.println(String.format("%s = %s", "a", (System.currentTimeMillis() - start))); threadPoolExecutor.shutdown(); } public static void b(){ CountDownLatch countDownLatch = new CountDownLatch(size); long start = System.currentTimeMillis(); for(int i = 0;i<size;++i){ int seq = i; CompletableFuture .runAsync(()->createFile("b", seq)) .whenComplete((r, e)->{ countDownLatch.countDown(); }); } try { countDownLatch.await(); System.out.println(String.format("%s = %s", "b", (System.currentTimeMillis() - start))); } catch (InterruptedException e) { e.printStackTrace(); } } public static void c(){ long start = System.currentTimeMillis(); IntStream.range(0, size) .parallel() .forEach(e -> { createFile("c", e); }); System.out.println(String.format("%s = %s", "c", (System.currentTimeMillis() - start))); } public static void createFile(String prefix, int name){ File file = new File("D:/files/" + prefix + "_" + name); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(content.getBytes()); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { // a(); //b(); c(); } }