亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

尚硅谷java學習筆記——JUC(java.util.concurrent)

2019-11-06 07:05:06
字體:
來源:轉載
供稿:網友

java 5.0 提供了 java.util.concurrent (簡稱JUC )包,在此包中增加了在并發編程中很常用的實用工具類,用于定義類似于線程的自定義子系統,包括線程池、異步 IO 和輕量級任務框架。提供可調的、靈活的線程池。還提供了設計用于多線程上下文中的 Collection 實現等。

一、volatile關鍵字、內存可見性

內存可見性

內存可見性(Memory Visibility)是指當某個線程正在使用對象狀態而另一個線程在同時修改該狀態,需要確保當一個線程修改了對象狀態后,其他線程能夠看到發生的狀態變化。

可見性錯誤是指當讀操作與寫操作在不同的線程中執行時,我們無法確保執行讀操作的線程能適時地看到其他線程寫入的值,有時甚至是根本不可能的事情。

我們可以通過同步來保證對象被安全地發布。除此之外我們也可以使用一種更加輕量級的 volatile 變量。

volatile 關鍵字

Java 提供了一種稍弱的同步機制,即 volatile 變量,用來確保將變量的更新操作通知到其他線程,可以保證內存中的數據可見??梢詫?volatile 看做一個輕量級的鎖,但是又與鎖有些不同:

對于多線程,不是一種互斥關系不能保證變量狀態的“原子性操作”public class TestVolatile { public static void main(String[] args){ ThreadDemo td=new ThreadDemo(); new Thread(td).start(); while(true){ if(td.isFlag()){ System.out.二、原子變量 、CAS

原子變量:jdk1.5 后 java.util.concurrent.atomic 類的小工具包,支持在單個變量上解除鎖的線程安全編程,包下提供了常用的原子變量: - AtomicBoolean 、AtomicInteger 、AtomicLong 、 AtomicReference - AtomicIntegerArray 、AtomicLongArray - AtomicMarkableReference - AtomicReferenceArray - AtomicStampedReference

1.類中的變量都是volatile類型:保證內存可見性 2.使用CAS算法:保證數據的原子性

CAS (Compare-And-Swap) 是一種硬件對并發的支持,針對多處理器操作而設計的處理器中的一種特殊指令,用于管理對共享數據的并發訪問。 CAS 是一種無鎖的非阻塞算法的實現。 CAS包含三個操作數: 內存值 V 預估值 A 更新值 B 當且僅當V==A時,B的值才更新給A,否則將不做任何操作。

public class TestAtomicDemo { public static void main(String[] args) { AtomicDemo ad = new AtomicDemo(); for (int i = 0; i < 10; i++) { new Thread(ad).start(); } }}class AtomicDemo implements Runnable{// private volatile int serialNumber = 0; private AtomicInteger serialNumber = new AtomicInteger(0); @Override public void run() { try { Thread.sleep(200); } catch (InterruptedException e) { } System.out.println(getSerialNumber()); } public int getSerialNumber(){ return serialNumber.getAndIncrement();//i++ 實際是int temp=i;i=i+1;i=temp; 需要原子性操作 }}

使用synchronized方法模擬CAS 算法,實際是由硬件機制完成的,用10個線程代表對內存中數據的10次修改請求。只有上個線程修改完,這個線程從內存中獲取的內存值當成期望值,才等于內存值,才能對內存值進行修改。

public class TestCompareAndSwap { public static void main(String[] args) { final CompareAndSwap cas=new CompareAndSwap(); for(int i=0;i<10;i++){ new Thread(new Runnable(){ @Override public void run() { int expectedValue=cas.get(); boolean b=cas.compareAndSwap(expectedValue, (int)(Math.random()*101)); System.out.println(b); } }).start(); } }}class CompareAndSwap{ private int value;//內存值 //獲取內存值 public synchronized int get(){ return value; } //比較 public synchronized boolean compareAndSwap(int expectedValue,int newValue){ int oldValue=value;//線程讀取內存值,與預估值比較 if(oldValue==expectedValue){ this.value=newValue; return true; } return false; }}

三、ConcurrentHashMap、鎖分段

HashMap 線程不安全 Hashtable 內部采用獨占鎖,線程安全,但效率低 ConcurrentHashMap同步容器類是java5 新增的一個線程安全的哈希表,效率介于HashMap和Hashtable之間。內部采用“鎖分段”機制。

java.util.concurrent 包還提供了設計用于多線程上下文中的Collection實現:

當期望許多線程訪問一個給定 collection 時, ConcurrentHashMap 通常優于同步的 HashMap, ConcurrentSkipListMap 通常優于同步的 TreeMap ConcurrentSkipListSet通常優于同步的 TreeSet.

當期望的讀數和遍歷遠遠大于列表的更新數時, CopyOnWriteArrayList 優于同步的 ArrayList。因為每次添加時都會進行復制,開銷非常的大,并發迭代操作多時 ,選擇。

四、CountDownLatch 閉鎖

CountDownLatch 一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。

閉鎖可以延遲線程的進度直到其到達終止狀態,閉鎖可以用來確保某些活動直到其他活動都完成才繼續執行: ? 確保某個計算在其需要的所有資源都被初始化之后才繼續執行; ? 確保某個服務在其依賴的所有其他服務都已經啟動之后才啟動; ? 等待直到某個操作所有參與者都準備就緒再繼續執行。

/* * CountDownLatch:閉鎖,在完成某些運算時,只有其他所有線程的運算全部完成,當前運算才繼續執行 */public class TestCountDownLatch { public static void main(String[] args) { final CountDownLatch latch=new CountDownLatch(50); LatchDemo ld=new LatchDemo(latch); long start=System.currentTimeMillis(); for(int i=0;i<50;i++){ new Thread(ld).start(); } try { latch.await(); //直到50個人子線程都執行完,latch的值減到0時,才往下執行 } catch (InterruptedException e) { e.printStackTrace(); } long end=System.currentTimeMillis(); System.out.println("耗費時間為:"+(end-start)); }}class LatchDemo implements Runnable{ private CountDownLatch latch; public LatchDemo(CountDownLatch latch){ this.latch=latch; } @Override public void run() { try{ for(int i=0;i<50000;i++){ if(i%2==0){ System.out.println(i); } } }finally{ latch.countDown();//latch的值減一 } }}

五、實現Callable接口

Java 5.0 在 java.util.concurrent 提供了一個新的創建執行線程的方式:Callable 接口

實現Callable 接口,相較于實現 Runnable接口的方式,方法可以有返回值,并且可以拋出異常。

Callable 需要依賴FutureTask ,用于接收返回值,FutureTask 也可以用作閉鎖。

/* * 一、創建執行線程的方式三:實現Callable接口。相較于實現Runnable接口的方式,方法可以有返回值,并且可以拋出異常。 * 二、執行Callable方式,需要FutureTask實現類的支持,用于接收運算結果。FutureTask是Future接口的實現類 */public class TestCallable { public static void main(String[] args) { ThreadDemo2 td=new ThreadDemo2(); //1.執行Callable方式,需要FutureTask實現類的支持,用于接收運行結果。 FutureTask<Integer> result=new FutureTask<>(td); new Thread(result).start(); //2.接收線程運算后的結果 try { Integer sum = result.get();//FutureTask 可用于 閉鎖 當子線程執行完畢,才會執行此后語句 System.out.println(sum); System.out.println("----------------------"); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }}class ThreadDemo2 implements Callable<Integer>{ @Override public Integer call() throws Exception { int sum=0; for(int i=0;i<=100000;i++){ sum+=i; } return sum; }}

六、Lock 同步鎖

在 Java 5.0 之前,協調共享對象的訪問時可以使用的機制只有 synchronized 和 volatile 。Java 5.0 后增加了一些新的機制,但并不是一種替代內置鎖的方法,而是當內置鎖不適用時,作為一種可選擇的高級功能。

ReentrantLock 實現了 Lock 接口,并提供了與synchronized 相同的互斥性和內存可見性。但相較于synchronized 提供了更高的處理鎖的靈活性。

/* * 一、用于解決多線程安全問題的方式: * synchronized:隱式鎖 * 1、同步代碼塊 * 2、同步方法 * jdk 1.5后 * 3、同步鎖 Lock * 注意:是一個顯式鎖,通過lock()方式上鎖,必須通過unlock()方法釋放鎖 */public class TestLock { public static void main(String[] args) { Ticket ticket=new Ticket(); new Thread(ticket,"1號窗口").start(); new Thread(ticket,"2號窗口").start(); new Thread(ticket,"3號窗口").start(); }}class Ticket implements Runnable{ private int tick=100; private Lock lock=new ReentrantLock(); @Override public void run() { while(true){ lock.lock(); try{ if(tick>0){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"完成售票為:"+--tick); } else{ break; } }finally{ lock.unlock();//釋放鎖一定要放在finally里,保證一定執行 } } }}/* * 生產者和消費者案例,優化,防止出現虛假喚醒,線程無法停止 */public class TestProductorAndConsumer { public static void main(String[] args) { Clerk clerk=new Clerk(); Productor pro=new Productor(clerk); Consumer cus=new Consumer(clerk); new Thread(pro,"生產者 A").start(); new Thread(cus,"消費者 B").start(); new Thread(pro,"生產者 C").start(); new Thread(cus,"消費者 D").start(); }}//店員 假如只有一個商品位置class Clerk{ private int product=0; //進貨 public synchronized void get(){ while(product>=1){//為了避免虛假喚醒問題,應該總是使用在循環中 System.out.println("產品已滿!"); try{ this.wait(); }catch(InterruptedException e){ } } System.out.println(Thread.currentThread().getName()+" : "+ ++product); this.notifyAll(); } //賣貨 public synchronized void sale(){ while(product<=0){ System.out.println("缺貨!"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" : "+ --product); this.notifyAll(); }}//生產者class Productor implements Runnable{ private Clerk clerk; public Productor(Clerk clerk){ this.clerk=clerk; } @Override public void run() { for(int i=0;i<20;i++){ try{ Thread.sleep(200); }catch(InterruptedException e){ } clerk.get(); } }}//消費者class Consumer implements Runnable{ private Clerk clerk; public Consumer(Clerk clerk){ this.clerk=clerk; } @Override public void run() { for(int i=0;i<20;i++){ clerk.sale(); } }}

七、Condition 控制線程通信

Condition 接口描述了可能會與鎖有關聯的條件變量。這些變量在用法上與使用 Object.wait 訪問的隱式監視器類似,但提供了更強大的功能。需要特別指出的是,單個 Lock 可能與多個 Condition 對象關聯。為了避免兼容性問題,Condition 方法的名稱與對應的 Object 版本中的不同。

在 Condition 對象中,與 wait、notify 和 notifyAll 方法對應的分別是await、signal 和 signalAll。

Condition 實例實質上被綁定到一個鎖上。要為特定 Lock 實例獲得Condition 實例,請使用其 newCondition() 方法。

public class TestProductorAndConsumerForLock { public static void main(String[] args) { Clerk clerk=new Clerk(); Productor pro=new Productor(clerk); Consumer cus=new Consumer(clerk); new Thread(pro,"生產者 A").start(); new Thread(cus,"消費者 B").start(); new Thread(pro,"生產者 C").start(); new Thread(cus,"消費者 D").start(); }}//店員 假如只有一個商品位置class Clerk{ private int product=0; private Lock lock=new ReentrantLock(); private Condition condition=lock.newCondition(); //進貨 public void get(){ lock.lock(); try{ while(product>=1){//為了避免虛假喚醒問題,應該總是使用在循環中 System.out.println("產品已滿!"); try{ condition.await();//this.wait(); }catch(InterruptedException e){ } } System.out.println(Thread.currentThread().getName()+" : "+ ++product); condition.signalAll();//this.notifyAll(); }finally{ lock.unlock(); } } //賣貨 public void sale(){ lock.lock(); try{ while(product<=0){ System.out.println("缺貨!"); try { condition.await();//this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" : "+ --product); condition.signalAll();//this.notifyAll(); }finally{ lock.unlock(); } }}//生產者class Productor implements Runnable{ private Clerk clerk; public Productor(Clerk clerk){ this.clerk=clerk; } @Override public void run() { for(int i=0;i<20;i++){ try{ Thread.sleep(200); }catch(InterruptedException e){ } clerk.get(); } }}//消費者class Consumer implements Runnable{ private Clerk clerk; public Consumer(Clerk clerk){ this.clerk=clerk; } @Override public void run() { for(int i=0;i<20;i++){ clerk.sale(); } }}

八、線程按序交替

編寫一個程序,開啟 3 個線程,這三個線程的 ID 分別為A、B、C,每個線程將自己的 ID 在屏幕上打印 10 遍,要求輸出的結果必須按順序顯示。如:ABCABCABC…… 依次遞歸

public class TestABCAlternate { public static void main(String[] args) { AlternateDemo ad=new AlternateDemo(); new Thread(new Runnable(){ @Override public void run() { for(int i=1;i<=20;i++){ ad.loopA(i); } } },"A").start(); new Thread(new Runnable(){ @Override public void run() { for(int i=1;i<=20;i++){ ad.loopB(i); } } },"B").start(); new Thread(new Runnable(){ @Override public void run() { for(int i=1;i<=20;i++){ ad.loopC(i); System.out.println("-----------------------------------"); } } },"C").start(); }}class AlternateDemo{ private int number=1;//當前正在執行線程的標記 private Lock lock=new ReentrantLock(); private Condition condition1=lock.newCondition(); private Condition condition2=lock.newCondition(); private Condition condition3=lock.newCondition(); /* * @param totalLoop:循環第幾輪 */ public void loopA(int totalLoop){ lock.lock(); try{ //1.判斷 if(number!=1){ condition1.await(); } //2.打印 System.out.println(Thread.currentThread().getName()+"/t"+totalLoop); //3.喚醒 number=2; condition2.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.unlock(); } } public void loopB(int totalLoop){ lock.lock(); try{ //1.判斷 if(number!=2){ condition2.await(); } //2.打印 System.out.println(Thread.currentThread().getName()+"/t"+totalLoop); //3.喚醒 number=3; condition3.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.unlock(); } } public void loopC(int totalLoop){ lock.lock(); try{ //1.判斷 if(number!=3){ condition3.await(); } //2.打印 System.out.println(Thread.currentThread().getName()+"/t"+totalLoop); //3.喚醒 number=1; condition1.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.unlock(); } }}

九、ReadWriteLock 讀寫鎖

ReadWriteLock 維護了一對相關的鎖,一個用于只讀操作,另一個用于寫入操作。只要沒有 writer,讀取鎖可以由多個 reader 線程同時保持。寫入鎖是獨占的。

ReadWriteLock 讀取操作通常不會改變共享資源,但執行寫入操作時,必須獨占方式來獲取鎖。對于讀取操作占多數的數據結構。 ReadWriteLock 能提供比獨占鎖更高的并發性。而對于只讀的數據結構,其中包含的不變性可以完全不需要考慮加鎖操作。

/* * 1.ReadWriteLock:讀寫鎖 * 寫寫|讀寫 需要"互斥" * 讀讀 不需要"互斥" */public class TestReadWriteLock { public static void main(String[] args) { ReadWriteLockDemo rw=new ReadWriteLockDemo(); new Thread(new Runnable() { @Override public void run() { rw.set((int)(Math.random()*101)); } },"Write").start(); for(int i=0;i<100;i++){ new Thread(new Runnable() { @Override public void run() { rw.get(); } }).start(); } }}class ReadWriteLockDemo{ private int number=0; private ReadWriteLock lock=new ReentrantReadWriteLock(); //讀 public void get(){ lock.readLock().lock();//上鎖 try{ System.out.println(Thread.currentThread().getName()+" : "+number); }finally{ lock.readLock().unlock();//釋放鎖 } } //寫 public void set(int number){ lock.writeLock().lock(); try{ System.out.println(Thread.currentThread().getName()); this.number=number; }finally{ lock.writeLock().unlock(); } }}

十、線程八鎖

一個對象里面如果有多個synchronized方法,某一個時刻內,只要一個線程去調用其中的一個synchronized方法了,其它的線程都只能等待,換句話說,某一個時刻內,只能有唯一一個線程去訪問這些synchronized方法。鎖的是當前對象this,被鎖定后,其它的線程都不能進入到當前對象的其它的synchronized方法。加個普通方法后發現和同步鎖無關換成兩個對象后,不是同一把鎖了,情況立刻變化。都換成靜態同步方法后,情況又變化所有的非靜態同步方法用的都是同一把鎖——實例對象本身,也就是說如果一個實例對象的非靜態同步方法獲取鎖后,該實例對象的其他非靜態同步方法必須等待獲取鎖的方法釋放鎖后才能獲取鎖,可是別的實例對象的非靜態同步方法因為跟該實例對象的非靜態同步方法用的是不同的鎖,所以毋須等待該實例對象已獲取鎖的非靜態同步方法釋放鎖就可以獲取他們自己的鎖。所有的靜態同步方法用的也是同一把鎖——類對象本身,這兩把鎖是兩個不同的對象,所以靜態同步方法與非靜態同步方法之間是不會有競態條件的。但是一旦一個靜態同步方法獲取鎖后,其他的靜態同步方法都必須等待該方法釋放鎖后才能獲取鎖,而不管是同一個實例對象的靜態同步方法之間,還是不同的實例對象的靜態同步方法之間,只是它們同一個類的實例對象!/* * 實驗:觀察打印的"one" or "two" ? * * 1.兩個普通同步方法,兩個線程,標準打印,打??? //one two 因為同步鎖是this(調用對象本身),被鎖定后,其它的線程都不能進入到當前對象的其它的synchronized方法 * 2.新增Thread.sleep()給 getOne(),打??? //等3秒后 one two * 3.新增普通方法(非同步) getThree(),打?。?/three 等3秒 one two 因為同步鎖不影響普通方法的執行 * 4.兩個普通同步方法,兩個Number對象,打印?//two 等3秒 one 因為用的不是同一把鎖,互不影響 * 5.修改 getOne() 為靜態同步方法,使用一個Number對象打印? //two 等3秒 one 因為靜態同步方法用的鎖是類對象本身,Number.class; 和對象用的是不同的鎖 * 6.修改兩個方法均為靜態同步方法,一個Number對象?//等3秒 one two 用的鎖都是Number類對象本身 * 7.一個靜態同步方法,一個非靜態同步方法,兩個Number對象?//two 等3秒one * 8.兩個靜態同步方法,兩個Number對象?//等3秒后 one two 用的鎖都是Number類對象本身 * * 線程八鎖的關鍵: * ①非靜態方法的鎖默認為 this, 靜態方法的鎖為 對應的 Class 實例 * ②某一個時刻內,只能有一個線程持有同一把鎖,無論幾個方法。 */public class TestThread8Monitor { public static void main(String[] args) { Number number = new Number(); Number number2 = new Number(); new Thread(new Runnable() { public void run() { number.getOne(); } }).start(); new Thread(new Runnable() { public void run() {// number.getTwo(); number2.getTwo(); } }).start();// new Thread(new Runnable() {// public void run() {// number.getThree();// }// }).start(); }}class Number { public static synchronized void getOne() { try { Thread.sleep(3000); } catch (InterruptedException e) { } System.out.println("one"); } public static synchronized void getTwo() { System.out.println("two"); }// public void getThree(){// System.out.println("three");// }}

十一、線程池

獲取線程第四種方法。 線程池可以解決兩個不同問題:由于減少了每個任務調用的開銷,它們通??梢栽趫绦写罅慨惒饺蝿諘r提供增強的性能,并且還可以提供綁定和管理資源(包括執行任務集時使用的線程)的方法。每個 ThreadPoolExecutor 還維護著一些基本的統計數據,如完成的任務數。

為了便于跨大量上下文使用,此類提供了很多可調整的參數和擴展鉤子 (hook)。但是,強烈建議程序員使用較為方便的 Executors 工廠方法 :

Executors.newCachedThreadPool()(無界線程池,可以進行自動線程回收)Executors.newFixedThreadPool(int)(固定大小線程池)Executors.newSingleThreadExecutor()(單個后臺線程)

它們均為大多數使用場景預定義了設置。

/* * 一、線程池:提供了一個線程隊列,隊列中保存著所有等待狀態的線程。避免了創建與銷毀額外開銷,提高了響應的速度。 * 二、線程池的體系結構: * java.util.concurrent.Executor:負責線程的使用與調度的根接口 * |--**ExecutorService 子接口:線程池的主要接口 * |--ThreadPoolExecutor 線程池的實現類 * |--ScheduledExecutorService 子接口:負責線程的調度 * |--ScheduledThreadPoolExecutor:繼承ThreadPoolExecutor,實現ScheduledExecutorService接口 * 三、工具類:Executors * 方法有: * ExecutorService newFixedThreadPool(): 創建固定大小的線程池 * ExecutorService newCachedThreadPool():緩存線程池,線程池的數量不固定,可以根據需要自動的更改數量。 * ExecutorService newSingleThreadExecutor():創建單個線程池。線程池中只有一個線程 * * ScheduledExecutorService newScheduledThreadPool():創建固定大小的線程,可以延遲或定時的執行任務。 * */public class TestThreadPool { public static void main(String[] args) { //1.創建線程池 ExecutorService pool=Executors.newFixedThreadPool(5); List<Future<Integer>> list=new ArrayList<>(); for (int i = 0; i < 10; i++) { Future<Integer> future=pool.submit(new Callable<Integer>(){ @Override public Integer call() throws Exception { int sum=0; for(int i=0;i<=100;i++){ sum+=i; } return sum; } }); list.add(future); } pool.shutdown(); for(Future<Integer> future:list){ try { System.out.println(future.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }}

十二、線程調度

public class TestScheduledThreadPool { public static void main(String[] args) throws Exception { ScheduledExecutorService pool=Executors.newScheduledThreadPool(5); for (int i = 0; i < 5; i++) { Future<Integer> result=pool.schedule(new Callable<Integer>() { @Override public Integer call() throws Exception { int num=new Random().nextInt(100);//生成隨機數 System.out.println(Thread.currentThread().getName()+" : "+num); return num; } }, 2, TimeUnit.SECONDS);//每次延遲兩秒后運行 System.out.println(result.get()); } }}

十三、ForkJoinPool 分支/ 合并框架 工作竊取

Fork/Join 框架:就是在必要的情況下,將一個大任務,進行拆分(fork)成若干個小任務(拆到不可再拆時),再將一個個的小任務運算的結果進行 join 匯總。

這里寫圖片描述

Fork/Join 框架與線程池的區別: 采用 “工作竊取”模式(work-stealing):相對于一般的線程池實現,fork/join框架的優勢體現在對其中包含的任務的處理方式上.在一般的線程池中,如果一個線程正在執行的任務由于某些原因無法繼續運行,那么該線程會處于等待狀態。而在fork/join框架實現中,如果某個子問題由于等待另外一個子問題 的完成而無法繼續運行。那么處理該子問題的線程會主動尋找其他尚未運行的子問題來執行.這種方式減少了線程的等待時間,提高了性能。

public class TestForkJoinPool { public static void main(String[] args) { Instant start=Instant.now(); ForkJoinPool pool=new ForkJoinPool(); ForkJoinTask<Long> task=new ForkJoinSumCalculate(0L, 50000000000L); Long sum=pool.invoke(task); System.out.println(sum); Instant end=Instant.now(); System.out.println("耗費時間為:"+Duration.between(start, end).toMillis());//耗費時間為:21020 } //一般的方法 @Test public void test1(){ Instant start=Instant.now(); long sum=0L; for(long i=0L;i<=50000000000L;i++){ sum+=i; } System.out.println(sum); Instant end=Instant.now(); System.out.println("耗費時間為:"+Duration.between(start, end).toMillis());//耗費時間為:27040 } //java8 新特性 @Test public void test2(){ Instant start=Instant.now(); Long sum=LongStream.rangeClosed(0L,50000000000L).parallel().reduce(0L, Long::sum); System.out.println(sum); Instant end=Instant.now(); System.out.println("耗費時間為:"+Duration.between(start, end).toMillis());//耗費時間為:14281 }}class ForkJoinSumCalculate extends RecursiveTask<Long>{ private static final long serialVersionUID=-54565646543212315L; private long start; private long end; private static final long THURSHOLD=10000L;//臨界值,小于這個值就不拆了,直接運算 public ForkJoinSumCalculate(long start,long end){ this.start=start; this.end=end; } @Override protected Long compute() { long length=end-start; if(length<=THURSHOLD){ long sum=0L; for(long i=start;i<=end;i++){ sum+=i; } return sum; }else{ //進行拆分,同時壓入線程隊列 long middle=(start+end)/2; ForkJoinSumCalculate left=new ForkJoinSumCalculate(start, middle); left.fork(); ForkJoinSumCalculate right=new ForkJoinSumCalculate(middle+1, end); right.fork(); return left.join()+right.join(); } }}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一精品自拍| 九九热精品在线| 亚洲成人久久网| 日韩高清电影好看的电视剧电影| 国产精品久久久久久久久免费看| 一区二区在线视频| 久久免费精品日本久久中文字幕| 日韩精品在线电影| 粉嫩av一区二区三区免费野| zzjj国产精品一区二区| 午夜精品久久久久久99热| 精品亚洲一区二区| 在线激情影院一区| 91精品国产综合久久久久久久久| 亚洲美女激情视频| 国产精品1区2区在线观看| 亚洲色图激情小说| 国产不卡视频在线| 国产免费一区二区三区在线观看| 亚洲国产精品成人一区二区| xxxx欧美18另类的高清| 亚洲男人天堂2023| 欧美极品xxxx| 国产一区二区三区在线| 在线精品91av| 亚洲网站在线观看| 国产美女精品视频免费观看| 国产欧美日韩亚洲精品| 精品久久久精品| 久久久噜久噜久久综合| 成人亚洲综合色就1024| 成人h猎奇视频网站| 亚洲综合在线播放| 国产精品av网站| 亚洲视频在线免费观看| 在线观看欧美日韩国产| 97精品一区二区三区| 久久久极品av| 久久久久久久久久国产| 欧美人与性动交a欧美精品| 欧美激情啊啊啊| 中文字幕亚洲在线| 色综合久久88色综合天天看泰| 欧美日本在线视频中文字字幕| 欧美另类老女人| 97国产精品视频| 欧美日韩性视频在线| 欧美成人一二三| 日韩欧美国产视频| 91精品视频在线免费观看| 国产精品日韩欧美综合| 91香蕉嫩草影院入口| 中文字幕免费国产精品| 91亚洲精品视频| 91中文精品字幕在线视频| 蜜臀久久99精品久久久久久宅男| 欧美黑人巨大xxx极品| 国产成人涩涩涩视频在线观看| 亚洲国产成人一区| 91亚洲人电影| 精品久久久久久中文字幕大豆网| 日韩成人中文电影| 91精品国产综合久久香蕉的用户体验| 亚洲国产日韩欧美在线99| 久久69精品久久久久久国产越南| 日韩专区在线观看| 日韩免费观看视频| 日韩亚洲第一页| 精品中文字幕在线| 久久久亚洲国产| 久热精品视频在线| 热99在线视频| 亚洲电影免费观看高清完整版在线| 中文字幕精品在线| 最新国产精品亚洲| 国产精品成人一区二区| 国产高清视频一区三区| 国产一区红桃视频| 欧美老女人bb| 日本高清不卡在线| 欧美整片在线观看| 亚洲国产天堂久久综合网| 在线亚洲国产精品网| 一区二区亚洲欧洲国产日韩| 26uuu日韩精品一区二区| 欧美黄色www| 不卡av日日日| 动漫精品一区二区| 精品免费在线观看| 欧美一级免费视频| 日韩视频中文字幕| 欧美在线一区二区三区四| 欧美一乱一性一交一视频| 国产成人精品日本亚洲专区61| 欧美在线视频观看| 欧美日韩国产黄| 日韩视频精品在线| 亚洲无限乱码一二三四麻| 成人国产精品日本在线| 欧美日韩免费看| 91色在线视频| 日韩精品视频免费| 国产精品免费网站| 国产精品免费久久久久影院| 国产精品老女人精品视频| 日韩av快播网址| 国产噜噜噜噜久久久久久久久| 亚洲自拍偷拍色片视频| 国产丝袜一区视频在线观看| 久久久精品一区二区| 亚洲va欧美va国产综合久久| 欧美精品久久一区二区| 日韩av中文字幕在线免费观看| 久久成年人视频| 国产精品毛片a∨一区二区三区|国| 日韩中文字幕在线免费观看| 欧美黑人xxxx| 国产色婷婷国产综合在线理论片a| 欧美性感美女h网站在线观看免费| 中文字幕自拍vr一区二区三区| 久久久久亚洲精品成人网小说| 亚洲经典中文字幕| 欧美国产日本在线| 国产三级精品网站| 国产精品视频一区国模私拍| 一区二区三区无码高清视频| 热99精品只有里视频精品| 国产成+人+综合+亚洲欧洲| 亚洲最大av网站| 免费av在线一区| 久久精品亚洲94久久精品| 久久久久久久久国产| www高清在线视频日韩欧美| 日韩视频免费在线观看| 伊人伊成久久人综合网站| 成人精品视频99在线观看免费| 亚洲最新中文字幕| 中文字幕亚洲综合久久筱田步美| 久久亚洲精品小早川怜子66| 2019亚洲男人天堂| 国产一区二区在线免费| 成人动漫网站在线观看| 国产精品欧美激情| 亚洲区中文字幕| 国产精品成人一区二区三区吃奶| 亚洲色图av在线| 国内精品久久久久久| 热re99久久精品国产66热| 亚洲精品www久久久久久广东| 欧美超级免费视 在线| 日韩在线视频观看正片免费网站| 欧美精品生活片| 成人午夜激情网| 欧美性视频网站| 国产成人综合一区二区三区| 亚洲性线免费观看视频成熟| 国内精品久久久久久| 日本亚洲欧洲色| 国产精品羞羞答答| 亚洲a区在线视频| 亚洲精品影视在线观看| 国产欧亚日韩视频| 欧美交受高潮1| 国产国语刺激对白av不卡|