🔥(大廠必備)廠長熬夜爆肝萬字之多執行緒高并發JUC編程(一)?學妹已收藏
關于作者
- 作者介紹
🍓 博客主頁:作者主頁
🍓 簡介:JAVA領域優質創作者🥇、一名在校大三學生🎓、在校期間參加各種省賽、國賽,斬獲一系列榮譽🏆,
🍓 關注我:關注我學習資料、檔案下載統統都有,每日定時更新文章,勵志做一名JAVA資深程式猿👨?💻,
JUC學習
文章目錄
- 🔥(大廠必備)廠長熬夜爆肝萬字之多執行緒高并發JUC編程(一)?學妹已收藏
- 關于作者
- JUC學習
- 1、什么是JUC
- 2、執行緒和行程
- 面試題:談一談wait和sleep區別?
- 3、Lock鎖(重點)
- 4、生產者消費者問題
- 5、8鎖現象
- 6、集合不安全
- 7、Callable
- 8、常用的輔助類
- 1) CountDownLatch—減法計數器
- 2) CyclicBarrier—加法計數器
- 3) Semaphore
- 9、讀寫鎖ReadwriteLock
- 10、堵塞佇列
- 1) 四組API
- 2) SynchronizedQueue 同步佇列
- 11、執行緒池
- 1) 執行緒池的好處:
- 2) 執行緒池: 三大方法
- 3) 七大引數
- 4) 拒絕策略
- 12、四大函式式介面
- 1) Function函式型介面
- 2) Predicate 斷定型介面
- 3) Suppier 供給型介面
- 4) Consummer 消費型介面
- 13、Stream 流式計算
- 14、ForkJoin—多線并發處理框架
- 1)ForkJoin 特點: 作業竊取!
- 2)如果使用ForkJoin
- ?????????最后(學妹照片)
1、什么是JUC

原始碼+官方檔案
JUC是 java util concurrent
面試高頻問JUC~!

java.util 是Java的一個工具包
業務:普通的執行緒代碼 Thread
Runnable: 沒有回傳值、效率相比于Callable 相對較低!

2、執行緒和行程
行程:一個程式,允許一個java程式會行程里面會出現一個java.exe;資料+代碼+pcb
一個行程可以包含多個執行緒,至少包含一個執行緒!
Java默認有幾個執行緒?2個執行緒! main執行緒、GC執行緒
執行緒:開了一個行程qq,聊天打字,訊息提示(執行緒負責的)
對于Java而言:Thread、Runable、Callable進行開啟執行緒的,
JAVA真的可以開啟執行緒嗎? 開不了的!
原因Java沒有權限去開啟執行緒、操作硬體的,這是一個native的一個本地方法,它呼叫的底層的C++代碼,
并發、并行
并發: 多執行緒操作同一個資源,
- CPU 只有一核,模擬出來多條執行緒,那么我們就可以使用CPU快速交替,來模擬多執行緒,
并行: 多個人并排行走,
- CPU多核,多個執行緒可以同時執行,
public class Test {
public static void main(String[] args) {
//獲取cpu的核數
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
并發編程的本質:充分利用CPU的資源!
執行緒的6個狀態
public enum State {
//創建
NEW,
//運行
RUNNABLE,
//阻塞
BLOCKED,
//等待
WAITING,
//超時等待
TIMED_WAITING,
//終止
TERMINATED;
}
面試題:談一談wait和sleep區別?
| 區別 | wait | sleep |
|---|---|---|
| 操作的類 | Object | Thread |
| 鎖的釋放 | 會釋放鎖 | 抱著鎖睡覺 |
| 范圍 | 同步代碼塊中 | 任何地方 |
| 例外捕獲 | 不需要捕獲例外 | 需要捕獲例外 |
3、Lock鎖(重點)
synchronized鎖問題
package com.zmz.day01;
/**
* @ProjectName: Juc
* @Package: com.zmz.day01
* @ClassName: TicketTest
* @Author: 張晟睿
* @Date: 2021/9/5 14:01
* @Version: 1.0
*/
//資源類 屬性 + 方法 oop
class Ticket{
private int num = 50;
//賣票方式 synchronized 本質:佇列 鎖
public synchronized void sale(){
if(num > 0){
System.out.println(Thread.currentThread().getName()+ " 賣出了第"+ num +" 張票,剩余:"+ --num +" 張票");
}
}
}
public class TicketTest {
public static void main(String[] args) {
//多線陳操作
//并發:多個執行緒操作同一個資源ticket
Ticket ticket = new Ticket();
//@FunctionalInterface 函式式介面 jdk1.8之后 lambda運算式
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"C").start();
}
}
Lock介面



公平鎖: 公平,必須先來后到~;
非公平鎖: 不公平,可以插隊;(默認為非公平鎖)
使用Lock進行操作
package com.zmz.day01;/**
* @ProjectName: Juc
* @Package: com.zmz.day01
* @ClassName: TicketTest2
* @Author: 張晟睿
* @Date: 2021/9/5 16:15
* @Version: 1.0
*/
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*@ClassName TicketTest2
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
class Ticket2{
/*
* 加鎖三步
* 1.實體化lock物件
* 2.lock加鎖
* 3.unlock解鎖
* */
Lock l = new ReentrantLock();
private int num = 50;
//賣票方式 synchronized 本質:佇列 鎖
public void sale(){
//加鎖
l.lock();
try {
//業務代碼
if(num > 0){
System.out.println(Thread.currentThread().getName()+ " 賣出了第"+ num +" 張票,剩余:"+ --num +" 張票");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//解鎖
l.unlock();
}
}
}
public class TicketTest2 {
public static void main(String[] args) {
//多線陳操作
//并發:多個執行緒操作同一個資源ticket
Ticket ticket = new Ticket();
//@FunctionalInterface 函式式介面 jdk1.8之后 lambda運算式
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"C").start();
}
}
| 區別 | synchronized | lock |
|---|---|---|
| 名稱 | 屬于關鍵字 | 屬于物件 |
| 狀態 | 不可以獲取鎖的狀態 | 可以獲取鎖的狀態 |
| 鎖的管理 | 自動釋放鎖 | 需要手動加鎖以及釋放鎖 |
| 執行緒 | 自己抱著鎖 | 等待 |
| 可重入鎖,不可以中斷的,非公平的 | 可重入的,可以判斷鎖,可以自己設定公平鎖和非公平鎖 | |
| 代碼同步 | 適合少量的代碼同步 | 適合大量的代碼同步 |
4、生產者消費者問題
synchronized版
package com.zmz.day01;
/**
* @ProjectName: Juc
* @Package: com.zmz.day01
* @ClassName: TicketTest3
* @Author: 張晟睿
* @Date: 2021/9/5 16:35
* @Version: 1.0
*/
/**
*@ClassName TicketTest3
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
public class TicketTest3 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//判斷等待 業務 喚醒
class Data{
private int number = 0;
// +1操作
public synchronized void increment() throws InterruptedException {
if(number != 0 ){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
// -1操作
public synchronized void decrement() throws InterruptedException{
if (number == 0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
}
問題存在,A執行緒B執行緒,現在如果我有四個執行緒A B C D!該怎么去解決問題

if判斷改為While判斷就可以解決虛假喚醒的問題,
package com.zmz.day01;
/**
* @ProjectName: Juc
* @Package: com.zmz.day01
* @ClassName: TicketTest3
* @Author: 張晟睿
* @Date: 2021/9/5 16:35
* @Version: 1.0
*/
/**
*@ClassName TicketTest3
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
//執行緒之間的通訊問題:生產者和消費者的問題! 等待喚醒,通知喚醒
//執行緒交替執行 A B操作同一個資源
public class TicketTest3 {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//判斷等待 業務 喚醒
class Data{
private int number = 0;
// +1操作
public synchronized void increment() throws InterruptedException {
while(number != 0 ){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
// -1操作
public synchronized void decrement() throws InterruptedException{
while (number == 0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
}
JUC版本的解決A B C D多執行緒的問題

package com.zmz.day01;
/**
* @ProjectName: Juc
* @Package: com.zmz.day01
* @ClassName: JucTest1
* @Author: 張晟睿
* @Date: 2021/9/5 19:34
* @Version: 1.0
*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*@ClassName JucTest1
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
public class JucTest1 {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(()->{for(int i=0;i<10;i++) {
data.increment();
}
},"A").start();
new Thread(()->{for(int i=0;i<10;i++) {
data.decrement();
}},"B").start();
new Thread(()->{for(int i=0;i<10;i++) {
data.increment();
}
},"C").start();
new Thread(()->{for(int i=0;i<10;i++) {
data.decrement();
}
},"D").start();
}
}
class Data2{
private int number = 0;
//lock鎖
Lock l = new ReentrantLock();
Condition condition = l.newCondition();
public void increment() {
l.lock();
try {
//業務
while (number!=0){
//等待操作
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
//通知其他執行緒 我+1完畢了
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
l.unlock();
}
}
public void decrement() {
l.lock();
try {
//業務
while (number==0){
//等待操作
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
//通知其他執行緒 我-1完畢了
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
l.unlock();
}
}
}
Condition的優勢:精準通知、喚醒的執行緒
package com.zmz.day01;
/**
* @ProjectName: Juc
* @Package: com.zmz.day01
* @ClassName: JucTest2
* @Author: 張晟睿
* @Date: 2021/9/5 19:52
* @Version: 1.0
*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
*@ClassName JucTest2
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
public class JucTest2 {
public static void main(String[] args) {
Data3 data3 = new Data3();
new Thread(()->{
for(int i=0;i<10;i++){
data3.printA();
}
},"A").start();
new Thread(()->{
for(int i=0;i<10;i++){
data3.printB();
}
},"B").start();
new Thread(()->{
for(int i=0;i<10;i++){
data3.printC();
}
},"C").start();
}
}
class Data3{
private Lock l = new ReentrantLock();
Condition condition1 = l.newCondition();
Condition condition2 = l.newCondition();
Condition condition3 = l.newCondition();
private int flag = 1;
public void printA(){
l.lock();
//判斷 -> 執行 -> 通知
try {
while(flag != 1){
//等待
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "->A" );
flag = 2;
//喚醒指定執行緒
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
l.unlock();
}
}
public void printB(){
l.lock();
//判斷 -> 執行 -> 通知
try {
while(flag != 2){
//等待
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "->BB" );
flag = 3;
//喚醒指定執行緒
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
l.unlock();
}
}
public void printC(){
l.lock();
//判斷 -> 執行 -> 通知
try {
while(flag != 3){
//等待
condition3.await();
}
System.out.println(Thread.currentThread().getName() + "->CCC" );
flag = 1;
//喚醒指定執行緒
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
l.unlock();
}
}
}
5、8鎖現象
1-2鎖
package com.zmz.lock8;/**
* @ProjectName: Juc
* @Package: com.zmz.lock8
* @ClassName: Test1
* @Author: 張晟睿
* @Date: 2021/9/5 21:18
* @Version: 1.0
*/
import java.util.concurrent.TimeUnit;
/**
*@ClassName Test1
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
/*
* 8鎖,就是關于鎖的8個問題
* 1、標準情況下,兩個執行緒先列印 發短信還是打電話? 發短信
* 2、sendSms方法延遲4s,兩個執行緒先列印 發短信還是打電話? 發短信
* */
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
//鎖存在
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
//synchronized鎖的物件是方法的呼叫者!
//兩個方法用的都是phone物件的鎖!
//誰先拿到誰執行!
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
public synchronized void call(){
System.out.println("打電話");
}
}

3-4鎖
package com.zmz.lock8;/**
* @ProjectName: Juc
* @Package: com.zmz.lock8
* @ClassName: Test2
* @Author: 張晟睿
* @Date: 2021/9/5 21:26
* @Version: 1.0
*/
import java.util.concurrent.TimeUnit;
/**
*@ClassName Test2
*@Description
*@Author 張晟睿
*@Date 2021/9/5
**/
//3、增加一個普通方法后! 發短信還是Hello,發短信 hello
//4、兩個物件,兩個同步方法,發短信還是打電話 打電話
public class Test2 {
public static void main(String[] args) {
//兩個物件,兩把鎖
Phone2 phone = new Phone2();
Phone2 phone2 = new Phone2();
//鎖存在
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone2{
//synchronized鎖的物件是方法的呼叫者!
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
public synchronized void call(){
System.out.println("打電話");
}
//這里沒有鎖!bubu不是同步方法,不受鎖的影響
public void hello(){
System.out.println("hello");
}
}


5-6鎖
package com.zmz.lock8;/**
* @ProjectName: Juc
* @Package: com.zmz.lock8
* @ClassName: Test3
* @Author: 張晟睿
* @Date: 2021/9/6 12:35
* @Version: 1.0
*/
import java.util.concurrent.TimeUnit;
/**
*@ClassName Test3
*@Description
*@Author 張晟睿
*@Date 2021/9/6
**/
/*
* 5、增加兩個靜態同步方法,只有一個物件,先列印發短信還是打電話? 發短信
* 6、兩個物件!增加兩個靜態同步方法,只有一個物件,先列印發短信還是打電話 發短信
* */
public class Test3 {
public static void main(String[] args) {
//兩個物件,兩個呼叫者,兩把鎖!
//兩個物件的class類模板只有一個,static,鎖的是Class
Phone3 phone = new Phone3();
Phone3 phone2 = new Phone3();
//鎖存在
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
//Phone3唯一的一個Class物件
class Phone3{
//synchronized鎖的物件是方法的呼叫者!
//static 靜態方法
//類一加載就有了!Class 模板 鎖的是Class
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
public static synchronized void call(){
System.out.println("打電話");
}
}

7-8鎖
package com.zmz.lock8;/**
* @ProjectName: Juc
* @Package: com.zmz.lock8
* @ClassName: Test4
* @Author: 張晟睿
* @Date: 2021/9/6 13:07
* @Version: 1.0
*/
import java.util.concurrent.TimeUnit;
/**
*@ClassName Test4
*@Description
*@Author 張晟睿
*@Date 2021/9/6
**/
/*
* 1個靜態同步方法,1個同步方法,1個物件 先列印發短信還是打電話? 打電話
* 1個靜態同步方法,1個同步方法,2個物件 先列印發短信還是打電話? 發短信
* */
public class Test4 {
public static void main(String[] args) {
//兩個物件,兩個呼叫者,兩把鎖!
//兩個物件的class類模板只有一個,static,鎖的是Class
Phone4 phone = new Phone4();
//鎖存在
new Thread(()->{
phone.sendSms();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
//Phone4唯一的一個Class物件
class Phone4{
//synchronized鎖的物件是方法的呼叫者!
//鎖的是Class類模板
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
//鎖的是呼叫者
public synchronized void call(){
System.out.println("打電話");
}
}

6、集合不安全
1、ArrayList集合不安全
package com;/**
* @ProjectName: Juc
* @Package: com
* @ClassName: unsafe
* @Author: 張晟睿
* @Date: 2021/9/6 19:37
* @Version: 1.0
*/
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
*@ClassName unsafe
*@Description
*@Author 張晟睿
*@Date 2021/9/6
**/
public class unsafe {
public static void main(String[] args) {
//高并發下的ArrayList真的安全么?
/**
* 解決方法
* 1、List<String> list = new Vector<String>();
* 2、List<String> list = Collections.synchronizedList(new ArrayList<>());
* 3、List<String> list = new CopyOnWriteArrayList<>();
* */
List<String> list = new CopyOnWriteArrayList<>();
//啟動10個多執行緒
for (int i = 1; i < 10; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 5));
System.out.println(list);
}, String.valueOf(i)).start();
}
}
}
CopyOnWriteArrayList原始碼分析

2、Set不安全
package com.zmz.unsafe;/**
* @ProjectName: Juc
* @Package: com.zmz.unsafe
* @ClassName: SetSafe
* @Author: 張晟睿
* @Date: 2021/9/6 21:20
* @Version: 1.0
*/
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
/**
*@ClassName SetSafe
*@Description
*@Author 張晟睿
*@Date 2021/9/6
**/
public class SetSafe {
public static void main(String[] args) {
//Set<String> set = new HashSet<>();
//Set<String> set = Collections.synchronizedSet(new HashSet<>());
Set<String> set = new CopyOnWriteArraySet<>();
for (int i = 1; i < 60; i++) {
new Thread(() -> {
set.add(UUID.randomUUID().toString().substring(0, 5));
System.out.println(set);
}, String.valueOf(i)).start();
}
}
}
HashSet原始碼
public HashSet() {
map = new HashMap<>();
}
//HashSet本質就是Map集合
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
private static final Object PRESENT = new Object();//不變的值
3、HashMap不安全
package com.zmz.unsafe;/**
* @ProjectName: Juc
* @Package: com.zmz.unsafe
* @ClassName: MapSafe
* @Author: 張晟睿
* @Date: 2021/9/6 21:27
* @Version: 1.0
*/
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
*@ClassName MapSafe
*@Description
*@Author 張晟睿
*@Date 2021/9/6
**/
public class MapSafe {
public static void main(String[] args) {
//Map<String,String> map = new HashMap<>();
//Map<String, Object> map = Collections.synchronizedMap(new HashMap<>());
Map<String, Object> map = new ConcurrentHashMap<>();
for (int i = 1; i <= 30; i++) {
new Thread(()->{
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5));
System.out.println(map);
},String.valueOf(i)).start();
}
}
}
7、Callable

- 可以有回傳值
- 可以拋出例外
- 方法不同,run()/call()
callable原始碼




代碼測驗
package com.zmz.callable;/**
* @ProjectName: Juc
* @Package: com.zmz.callable
* @ClassName: CallableTest
* @Author: 張晟睿
* @Date: 2021/10/3 16:52
* @Version: 1.0
*/
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
*@ClassName CallableTest
*@Description
*@Author 張晟睿
*@Date 2021/10/3
**/
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// new Thread(new Runnable()).start();
// new Thread(new FutureTask<V>()).start();
// new Thread(new FutureTask<V>( Callable )).start();
new Thread().start();
MyThread myThread = new MyThread();
FutureTask futureTask = new FutureTask(myThread);//適配類
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); //結果存在快取提交效率
Integer o = (Integer) futureTask.get();//獲取回傳的結果
//這個get方法可以會產生阻塞! 解決辦法 放到最后一行或者異步通信
System.out.println(o);
}
}
class MyThread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("call()方法");
//耗時操作
return 1024;
}
}
/*
1、有快取
2、結果可能會等待,阻塞
*/
8、常用的輔助類
1) CountDownLatch—減法計數器
package com.zmz.assist;/**
* @ProjectName: Juc
* @Package: com.zmz.assist
* @ClassName: CountDownLatchDemo
* @Author: 張晟睿
* @Date: 2021/10/3 18:00
* @Version: 1.0
*/
import java.util.concurrent.CountDownLatch;
/**
*@ClassName CountDownLatchDemo
*@Description
*@Author 張晟睿
*@Date 2021/10/3
**/
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch count = new CountDownLatch(10);
for (int i = 1; i <= 10; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "Go out");
count.countDown();//數量-1
},String.valueOf(i)).start();
}
count.await();//等計數器歸零,然后再往下執行
System.out.println("Close Door");
}
}
原理:
- count.countDown();//數量-1
- count.await();//等待計數器歸零,然后再向下執行
每次有執行緒用countDown()數量-1,如果計算器變為0了,然后count.await()就被喚醒,繼續下面的執行!
2) CyclicBarrier—加法計數器
package com.zmz.assist;/**
* @ProjectName: Juc
* @Package: com.zmz.assist
* @ClassName: CycilcBarrierDemo
* @Author: 張晟睿
* @Date: 2021/10/3 18:23
* @Version: 1.0
*/
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
*@ClassName CycilcBarrierDemo
*@Description
*@Author 張晟睿
*@Date 2021/10/3
**/
public class CycilcBarrierDemo {
public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(7,()->{
System.out.println("你已經湊齊了七顆龍珠!可以變身了");
});
for (int i = 1; i <= 7; i++) {
final int temp = i;
new Thread(()->{
System.out.println(Thread.currentThread().getName()+ "收集" +(temp) +"顆龍珠");
try {
barrier.await();//等待
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
3) Semaphore
Semaphore:信號量,很多時候用來處理高并發,

package com.zmz.assist;/**
* @ProjectName: Juc
* @Package: com.zmz.assist
* @ClassName: SemaphoreDemo
* @Author: 張晟睿
* @Date: 2021/10/3 19:32
* @Version: 1.0
*/
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/**
*@ClassName SemaphoreDemo
*@Description
*@Author 張晟睿
*@Date 2021/10/3
**/
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <= 6; i++) {
new Thread(()->{
try {
semaphore.acquire();//獲得
System.out.println(Thread.currentThread().getName()+"得到車位");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"離開車位");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();//釋放
}
},String.valueOf(i)).start();
}
}
}
原理:
-
acquire():獲得,假設已經滿了組需要等待,直到被釋放為止
-
release():釋放,會將當前的信號量釋放+1,然后喚醒等待的執行緒!
作用:多個共享的資源互斥使用!并發限流控制最大的執行緒數量!
9、讀寫鎖ReadwriteLock

package com.zmz.lock;/**
* @ProjectName: Juc
* @Package: com.zmz.lock
* @ClassName: ReadwritelockDemo
* @Author: 張晟睿
* @Date: 2021/10/3 20:48
* @Version: 1.0
*/
import java.util.HashMap;
import java.util.Map;
/**
*@ClassName ReadwritelockDemo
*@Description
*@Author 張晟睿
*@Date 2021/10/3
**/
public class ReadwritelockDemo {
public static void main(String[] args) {
Mycache mycache = new Mycache();
//寫入
for (int i = 1; i < 6; i++) {
final int temp = i;
new Thread(()->{
mycache.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
//讀取
for (int i = 1; i < 6; i++) {
final int temp = i;
new Thread(()->{
mycache.get(temp+"");
},String.valueOf(i)).start();
}
}
}
class Mycache{
private volatile Map<String , Object> map = new HashMap<>();
public void put(String key, Object value){
System.out.println(Thread.currentThread().getName() + "寫入" + key);
map.put(key,value);
System.out.println(Thread.currentThread().getName() + "寫入完成");
}
public void get(String key){
System.out.println(Thread.currentThread().getName() + "讀取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "讀取完成");
}
}
/*
1寫入1
5寫入5
5寫入完成
4寫入4
4寫入完成
3寫入3
2寫入2
1讀取1
3寫入完成
1寫入完成
2讀取2
2讀取完成
3讀取3
3讀取完成
1讀取完成
2寫入完成
5讀取5
5讀取完成
4讀取4
4讀取完成
*/
我們可以看到出現了嚴重的插隊問題!該如何去解決囊?我們使用讀寫鎖來解決插隊的問題,
修改后的操作
package com.zmz.lock;/**
* @ProjectName: Juc
* @Package: com.zmz.lock
* @ClassName: ReadwritelockDemo
* @Author: 張晟睿
* @Date: 2021/10/3 20:48
* @Version: 1.0
*/
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @ClassName ReadwritelockDemo
* @Description
* @Author 張晟睿
* @Date 2021/10/3
**/
/*
*獨占鎖 (寫鎖)一次只能被一個執行緒占有
*共享鎖 (讀鎖)多個執行緒可以同時占有
* ReadWriteLock
* 讀-讀 可以共存
* 讀-寫 不可以共存
* 寫-寫 不可以共存
* */
public class ReadwritelockDemo {
public static void main(String[] args) {
MycacheLock mycache = new MycacheLock();
//寫入
for (int i = 1; i < 6; i++) {
final int temp = i;
new Thread(() -> {
mycache.put(temp + "", temp + "");
}, String.valueOf(i)).start();
}
//讀取
for (int i = 1; i < 6; i++) {
final int temp = i;
new Thread(() -> {
mycache.get(temp + "");
}, String.valueOf(i)).start();
}
}
}
//加鎖
class MycacheLock {
private volatile Map<String, Object> map = new HashMap<>();
//讀寫鎖:更加細粒度的控制
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
//存、寫的時候,只希望同時只有一個執行緒寫
public void put(String key, Object value) {
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "寫入" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "寫入完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.writeLock().unlock();
}
}
//取、讀所有人都可以進行操作
public void get(String key) {
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "讀取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "讀取完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
readWriteLock.readLock().unlock();
}
}
}
class Mycache {
private volatile Map<String, Object> map = new HashMap<>();
public void put(String key, Object value) {
System.out.println(Thread.currentThread().getName() + "寫入" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "寫入完成");
}
public void get(String key) {
System.out.println(Thread.currentThread().getName() + "讀取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "讀取完成");
}
}
/*
1寫入1
1寫入完成
2寫入2
2寫入完成
3寫入3
3寫入完成
4寫入4
4寫入完成
5寫入5
5寫入完成
1讀取1
1讀取完成
5讀取5
3讀取3
3讀取完成
4讀取4
4讀取完成
5讀取完成
2讀取2
2讀取完成
*/
我們可以看到輸出的結果在寫入的時候有序的進行,讀操作的時候可以無序的進行,可以看到已經到達我們預期的效果😊
10、堵塞佇列
堵塞




什么情況下我們使用阻塞佇列:多執行緒并發處理,執行緒池!
10.1 學會使用佇列
添加、移除元素,現在有四組API
1) 四組API
| 方法 | 拋出例外 | 不會拋出例外,有回傳值 | 阻塞等待 | 超時等待 |
|---|---|---|---|---|
| 添加 | add() | offer() | put() | offer(E e, long timeout, TimeUnit unit) |
| 移除 | remove() | poll() | take() | poll(long timeout, TimeUnit unit) |
| 判斷首部 | element() | peek() | - | - |
/*
* 拋出例外
* */
public static void test1(){
//佇列大小3
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("a"));
System.out.println(blockingQueue.add("b"));
System.out.println(blockingQueue.add("c"));
//IllegalState ExceptionQueue full 拋出例外
//System.out.println(blockingQueue.add("d"));
//檢測隊首元素
System.out.println(blockingQueue.element()); System.out.println("================================================");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
//java.util.NoSuchElementException 拋出例外
//System.out.println(blockingQueue.remove());
}
/*
* 不拋出例外,有回傳值
* */
public static void test2(){
//佇列大小3
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
//false
System.out.println(blockingQueue.offer("d"));
//檢測隊首元素
System.out.println(blockingQueue.peek());
System.out.println("================================================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
//null
System.out.println(blockingQueue.poll());
}
/*
* 阻塞等待之?死死的等待
* */
public static void test3() throws InterruptedException {
//佇列大小3
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
//blockingQueue.put("d");
//無檢測隊首元素
System.out.println("================================================");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//System.out.println(blockingQueue.take());
}
/*
* 等待阻塞(超時)
* */
public static void test4() throws InterruptedException {
//佇列大小3
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(3);
blockingQueue.offer("a");
blockingQueue.offer("b");
blockingQueue.offer("c");
blockingQueue.offer("d",2, TimeUnit.SECONDS);
//無檢測隊首元素
System.out.println("================================================");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
blockingQueue.poll(2,TimeUnit.SECONDS);
}
2) SynchronizedQueue 同步佇列
沒有容量,進去一個元素,必須等待取出來之后,才能再往里面放一個元素
put take
package com.zmz.queue;
/**
* @ProjectName: Juc
* @Package: com.zmz.queue
* @ClassName: SyncQueue
* @Author: 張晟睿
* @Date: 2021/10/8 14:18
* @Version: 1.0
*/
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
/**
* 同步佇列
* 和其他的lockQueue 不一樣, SynchronousQueue 不存盤元素
*/
public class SyncQueue {
public static void main(String[] args) {
SynchronousQueue<String> synchronousQueue = new SynchronousQueue<>(); //同步佇列
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "put 1");
synchronousQueue.put("1");
System.out.println(Thread.currentThread().getName() + "put 2");
synchronousQueue.put("2");
System.out.println(Thread.currentThread().getName() + "put 3");
synchronousQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"Thread1").start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "=>" + synchronousQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
},"Thread2").start();
}
}
/*
Thread1put 1
Thread2=>1
Thread1put 2
Thread2=>2
Thread1put 3
Thread2=>3
*/
11、執行緒池
執行緒池有三大方法,七大引數,四種拒絕策略
程式的運行,本質: 占用系統的資源 ! 優化CPU資源的使用 ===>池化技術
執行緒池, 連接池, 記憶體池, 物件池///…
池化技術: 實作準備好一些資源, 有人要用,就來我這里拿,用完之后還給我
1) 執行緒池的好處:
- 降低資源消耗
- 提高回應速度
- 方便管理
執行緒復用,可以控制最大并發數,管理執行緒
2) 執行緒池: 三大方法
- ExecutorService service = Executors.newSingleThreadExecutor();//單個執行緒
- ExecutorService service = Executors.newFixedThreadPool(5);//創建一個固定的執行緒池的大小
- ExecutorService service = Executors.newCachedThreadPool();//可伸縮的,
package com.zmz.Pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @ProjectName: Juc
* @Package: com.zmz.ThreadPool
* @ClassName: ThreadPool
* @Author: 張晟睿
* @Date: 2021/10/8 16:44
* @Version: 1.0
*/
public class ThreadPool {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();//單個執行緒
ExecutorService threadPool2 = Executors.newFixedThreadPool(5); //創建一個固定的執行緒池的大小
ExecutorService threadPool3 = Executors.newCachedThreadPool(); //可伸縮的
//執行緒池用完必須要關閉執行緒池
try {
for (int i = 1; i <=100 ; i++) {
//通過執行緒池創建執行緒
threadPool3.execute(()->{
System.out.println(Thread.currentThread().getName()+ " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool3.shutdown();
}
}
}
3) 七大引數
public ThreadPoolExecutor(int corePoolSize, //核心執行緒池大小
int maximumPoolSize, //最大的執行緒池大小
long keepAliveTime, //超時了沒有人呼叫就會釋放
TimeUnit unit, //超時單位
BlockingQueue<Runnable> workQueue, //阻塞佇列
ThreadFactory threadFactory, //執行緒工廠 創建執行緒的 一般不用動
RejectedExecutionHandler handler //拒絕策略
) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}


package com.zmz.Pool;
import java.util.concurrent.*;
/**
* @ProjectName: Juc
* @Package: com.zmz.Pool
* @ClassName: ThreadPoolExecutorTest
* @Author: 張晟睿
* @Date: 2021/10/8 16:59
* @Version: 1.0
*/
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
// 獲取cpu 的核數
int max = Runtime.getRuntime().availableProcessors();
ExecutorService service =new ThreadPoolExecutor(
2,//核心執行緒池大小
max,//最大的執行緒池大小
3,//超時了沒有人呼叫就會釋放
TimeUnit.SECONDS,//超時單位
new LinkedBlockingDeque<>(3),//阻塞佇列
Executors.defaultThreadFactory(),//執行緒工廠 創建執行緒的
new ThreadPoolExecutor.AbortPolicy()//拒絕策略
);
try {
for (int i = 1; i <= 5; i++) {
service.execute(() -> {
System.out.println(Thread.currentThread().getName() + "運行成功");
});
}
}catch (Exception e) {
e.printStackTrace();
}
finally {
service.shutdown();
}
}
}
4) 拒絕策略

- new ThreadPoolExecutor.AbortPolicy() 超出最大處理執行緒拋出例外
- new ThreadPoolExecutor.CallerRunsPolicy() 從哪個執行緒創建就由那個執行緒執行
- new ThreadPoolExecutor.DiscardPolicy() 佇列滿了不會拋出例外
- new ThreadPoolExecutor.DiscardOldestPolicy() 嘗試去和第一個競爭,也不會拋出例外
12、四大函式式介面
新時代的程式員👨?💻:lambda運算式、鏈式編程、函式式介面、Stream流式計算

1) Function函式型介面

package com.zmz.FourFunction;
import java.util.function.Function;
/**
* @ProjectName: Juc
* @Package: com.zmz.FourFunction
* @ClassName: functionDemo
* @Author: 張晟睿
* @Date: 2021/10/8 17:15
* @Version: 1.0
*/
public class functionDemo {
public static void main(String[] args) {
Function<String, String> function = (str) -> {
return str;
};
System.out.println(function.apply("Hello,zmz!"));
}
}
2) Predicate 斷定型介面

package com.zmz.FourFunction;
import java.util.function.Predicate;
/**
* @ProjectName: Juc
* @Package: com.zmz.FourFunction
* @ClassName: PredicateDemo
* @Author: 張晟睿
* @Date: 2021/10/8 17:18
* @Version: 1.0
*/
public class PredicateDemo {
public static void main(String[] args) {
Predicate<String> predicate = (str) -> {return str.isEmpty();};
// false
System.out.println(predicate.test("zmz"));
// true
System.out.println(predicate.test(""));
}
}
3) Suppier 供給型介面

package com.zmz.FourFunction;
import java.util.function.Supplier;
/**
* @ProjectName: Juc
* @Package: com.zmz.FourFunction
* @ClassName: SuppierDemo
* @Author: 張晟睿
* @Date: 2021/10/8 17:21
* @Version: 1.0
*/
public class SuppierDemo {
public static void main(String[] args) {
Supplier<String> supplier = ()->{return "1024";};
System.out.println(supplier.get());
}
}
4) Consummer 消費型介面

package com.zmz.FourFunction;
import java.util.function.Consumer;
/**
* @ProjectName: Juc
* @Package: com.zmz.FourFunction
* @ClassName: ConsummerDemo
* @Author: 張晟睿
* @Date: 2021/10/8 17:21
* @Version: 1.0
*/
public class ConsummerDemo {
public static void main(String[] args) {
Consumer<String> consumer = (str)->{
System.out.println(str);
};
consumer.accept("zmz");
}
}
13、Stream 流式計算
package com.zmz.Stream;
/**
* @ProjectName: Juc
* @Package: com.zmz.Stream
* @ClassName: User
* @Author: 張晟睿
* @Date: 2021/10/8 18:01
* @Version: 1.0
*/
public class User {
private int id;
private String name;
private int age;
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.zmz.Stream;
/**
* @ProjectName: Juc
* @Package: com.zmz.Stream
* @ClassName: StreamDemo
* @Author: 張晟睿
* @Date: 2021/10/8 18:00
* @Version: 1.0
*
* * 題目要求: 用一行代碼實作
* * 1. Id 必須是偶數
* * 2.年齡必須大于23
* * 3. 用戶名轉為大寫
* * 4. 用戶名倒序
* * 5. 只能輸出一個用戶
*/
import java.util.Arrays;
import java.util.List;
public class StreamDemo {
public static void main(String[] args) {
User u1 = new User(1, "a", 23);
User u2 = new User(2, "b", 23);
User u3 = new User(3, "c", 23);
User u4 = new User(6, "d", 24);
User u5 = new User(4, "e", 25);
List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
// lambda、鏈式編程、函式式介面、流式計算
list.stream()
.filter(user -> {return user.getId()%2 == 0;})
.filter(user -> {return user.getAge() > 20;})
.map(user -> {return user.getName().toUpperCase();})
.sorted((user1, user2) -> {return user2.compareTo(user1);})
.limit(1)
.forEach(System.out::println);
}
}
14、ForkJoin—多線并發處理框架
什么是ForkJoin?
ava.util.concurrent.ForkJoinPool由Java大師Doug Lea主持撰寫,它可以將一個大的任務拆分成多個子任務進行并行處理,最后將子任務結果合并成最后的計算結果,并進行輸出,本文中對Fork/Join框架的講解,基于JDK1.8+中的Fork/Join框架實作,參考的Fork/Join框架主要源代碼也基于JDK1.8+,
這幾篇文章將試圖解釋Fork/Join框架的知識點,以便對自己、對各位讀者在并發程式的設計思路上進行一些啟發,文章將首先講解Fork/Join框架的基本使用,以及其中需要注意的使用要點;接著使用Fork/Join框架解決一些實際問題;最后再講解Fork/Join框架的作業原理,

1)ForkJoin 特點: 作業竊取!

2)如果使用ForkJoin
第一步,通過ForkJoinPool來執行
第二步,計算任務 execute(ForkJoinTask<?> task)
第三步,計算類要去繼承ForkJoinTask
ForkJoin 的計算類
ForkJoinComputer.java
package com.zmz.ForkJoin;
import java.util.concurrent.RecursiveTask;
/**
* @ProjectName: Juc
* @Package: com.zmz.ForkJoin
* @ClassName: ForkJoinComputer
* @Author: 張晟睿
* @Date: 2021/10/9 15:17
* @Version: 1.0
*/
public class ForkJoinComputer extends RecursiveTask<Long> {
private long start;
private long end;
/** 臨界值 */
private long temp = 1000000L;
public ForkJoinComputer(long start, long end) {
this.start = start;
this.end = end;
}
/**
* 計算方法
* @return
*/
@Override
protected Long compute() {
if ((end - start) < temp) {
Long sum = 0L;
for (Long i = start; i < end; i++) {
sum += i;
}
return sum;
}else {
// 使用ForkJoin 分而治之 計算
//1 . 計算平均值
long middle = (start + end) / 2;
ForkJoinComputer forkJoinDemo1 = new ForkJoinComputer(start, middle);
// 拆分任務,把執行緒壓入執行緒佇列
forkJoinDemo1.fork();
ForkJoinComputer forkJoinDemo2 = new ForkJoinComputer(middle, end);
forkJoinDemo2.fork();
long taskSum = forkJoinDemo1.join() + forkJoinDemo2.join();
return taskSum;
}
}
}
測驗類 ForkJoinTest.java
package com.zmz.ForkJoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
/**
* @ProjectName: Juc
* @Package: com.zmz.ForkJoin
* @ClassName: ForkJoinTest
* @Author: 張晟睿
* @Date: 2021/10/9 15:18
* @Version: 1.0
*/
public class ForkJoinTest {
private static final long SUM = 20_0000_0000;
public static void main(String[] args) throws ExecutionException, InterruptedException {
test1();
test2();
test3();
}
/**
* 使用普通方法
*/
public static void test1() {
long star = System.currentTimeMillis();
long sum = 0L;
for (long i = 1; i < SUM ; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println(sum);
System.out.println("普通程式猿——時間:" + (end - star));
System.out.println("============================");
}
/**
* 使用ForkJoin 方法
*/
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinComputer(0L, SUM);
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
Long along = submit.get();
System.out.println(along);
long end = System.currentTimeMillis();
System.out.println("中級程式猿——時間:" + (end - start));
System.out.println("--------------");
}
/**
* 使用 Stream 流計算
*/
public static void test3() {
long start = System.currentTimeMillis();
long sum = LongStream.range(0L, 20_0000_0000L).parallel().reduce(0, Long::sum);
System.out.println(sum);
long end = System.currentTimeMillis();
System.out.println("高級程式猿——時間:" + (end - start));
System.out.println("--------------");
System.out.println("============================");
}
}

分析一下高級程式猿的處理:

.parallel().reduce(0, Long::sum)使用一個并行流去計算整個計算,提高效率,
?????????最后(學妹照片)
附一張學妹的照片

?學妹都已經收藏了!!!?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/307226.html
標籤:java
下一篇:MySQL資料庫——事務和索引
