Java異步處理機(jī)制實(shí)例詳解
通常同步意味著一個(gè)任務(wù)的某個(gè)處理過(guò)程會(huì)對(duì)多個(gè)線程在用串行化處理,而異步則意味著某個(gè)處理過(guò)程可以允許多個(gè)線程同時(shí)處理。下面我們就來(lái)看看有關(guān)異步處理的詳細(xì)內(nèi)容。
異步通常代表著更好的性能,因?yàn)樗艽蟪潭壬弦蕾囉诰彌_,是典型的使用空間換時(shí)間的做法,例如在計(jì)算機(jī)當(dāng)中,高速緩存作為cpu和磁盤io之間的緩沖地帶協(xié)調(diào)cpu高速計(jì)算能力和磁盤的低速讀寫能力。
volatile
應(yīng)用場(chǎng)景:檢查一個(gè)應(yīng)用執(zhí)行關(guān)閉或中斷狀態(tài)。因?yàn)榇岁P(guān)鍵字拒絕了虛擬對(duì)一個(gè)變量多次賦值時(shí)的優(yōu)化從而保證了虛擬機(jī)一定會(huì)檢查被該關(guān)鍵字修飾的變量的狀態(tài)變化。
CountDownLatch
應(yīng)用場(chǎng)景:控制在一組線程操作執(zhí)行完成之前當(dāng)前線程一直處于等待。例如在主線程中執(zhí)行await()方法阻塞主線程,在工作線程執(zhí)行完邏輯后執(zhí)行countDown()方法。
本文示例場(chǎng)景:
1,從控制臺(tái)發(fā)送消息到消息服務(wù)器(由一個(gè)隊(duì)列模擬)。
2,將消息隊(duì)列寫入到文件(對(duì)寫文件的操作設(shè)置延時(shí)以模擬性能瓶頸)。
3,消息服務(wù)器作為控制臺(tái)和文件寫入之間的緩沖區(qū)。
示例代碼:
注:往消息隊(duì)列添加消息可以通過(guò)for循環(huán)一次性加入,本文為了便于觀察文件和隊(duì)列的變化而采用了控制臺(tái)輸入,實(shí)際寫一行文件記錄速度應(yīng)該高于手速,所以本文示例中增加了線程sleep時(shí)間。
package org.wit.ff.ch2;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
*
* <pre>
* 簡(jiǎn)單異步處理示例.
* </pre>
*
* @author F.Fang
* @version $Id: AsyncHandler.java, v 0.1 2014年10月23日 下午11:37:54 F.Fang Exp $
*/
public class AsyncHandler {
/**
* 控制資源釋放.
*/
private CountDownLatch latch;
/**
* 處理完成標(biāo)識(shí).
*/
private volatile boolean handleFinish;
/**
* 消息寫入本地文件完成.
*/
private volatile boolean sendFinish;
/**
* 阻塞隊(duì)列.
*/
private BlockingQueue<String> queue;
private BufferedWriter bw;
public AsyncHandler(CountDownLatch latch) {
this.latch = latch;
/**
* 使用鏈表實(shí)現(xiàn).
*/
queue = new LinkedBlockingQueue<String>();
File file = new File("E:/hello.txt");
try {
bw = new BufferedWriter(new FileWriter(file));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void handle() {
// 模擬性能瓶頸的執(zhí)行過(guò)程,3s處理一條消息.
new Thread() {
public void run() {
while (!handleFinish) {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e1) {
// 不做處理.
}
String s = queue.peek();
if (s != null) {
queue.poll();
try {
bw.write(s);
bw.newLine();
} catch (IOException e) {
}
}
// 若隊(duì)列為空并且消息發(fā)送完成.
if (queue.isEmpty() && sendFinish) {
// 計(jì)數(shù)器1->0
latch.countDown();
// 讓處理過(guò)程結(jié)束.
handleFinish = true;
break;
}
}
}
}.start();
}
/**
*
* <pre>
* 給出消息發(fā)送完成的標(biāo)識(shí).
* </pre>
*
*/
public void sendFinish() {
sendFinish = true;
}
/**
*
* <pre>
* 資源釋放.
* </pre>
*
*/
public void release() {
System.out.println("release!");
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
// TODO 打印日志.
}
}
//其實(shí)使用queue = null就夠了.
if (queue != null) {
queue.clear();
queue = null;
}
}
/**
*
* <pre>
* 往隊(duì)列發(fā)送消息.
* </pre>
*
* @param text
*/
public void sendMsg(String text) {
if (text != null && !text.isEmpty()) {
queue.add(text);
}
}
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
AsyncHandler handler = new AsyncHandler(latch);
handler.handle();
// 做一次檢查.
Scanner scanner = new Scanner(System.in);
while (true) {
String text = scanner.next();
// 若用戶選擇退出.
if ("exit".equals(text)) {
// 表示消息已經(jīng)發(fā)送完成.
handler.sendFinish();
break;
}
handler.sendMsg(text);
}
try {
// 阻塞主線程等待消息寫入到本地文件完成.
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 釋放資源 文件流,隊(duì)列.
handler.release();
// 關(guān)閉控制臺(tái)輸入.
scanner.close();
}
}
總結(jié)
以上就是本文關(guān)于異步機(jī)制的全部?jī)?nèi)容,實(shí)例代碼中的注釋還是比較詳細(xì)的,如果有什么問(wèn)題可以留言,小編會(huì)及時(shí)回復(fù)大家。同時(shí)也感謝大家對(duì)本站的支持!
相關(guān)文章
詳解Java并發(fā)工具類之CountDownLatch和CyclicBarrier
在JDK的并發(fā)包中,有幾個(gè)非常有用的并發(fā)工具類,它們分別是:CountDownLatch、CyclicBarrier、Semaphore和Exchanger,本文主要來(lái)講講其中CountDownLatch和CyclicBarrier的使用,感興趣的可以了解一下2023-06-06
SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例
這篇文章主要介紹了SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
工廠方法模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了工廠方法模式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理的相關(guān)資料,需要的朋友可以參考下2017-08-08
關(guān)于SpringBoot配置文件application.properties的路徑問(wèn)題
這篇文章主要介紹了關(guān)于SpringBoot配置文件application.properties的路徑問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
使用SpringAop動(dòng)態(tài)獲取mapper執(zhí)行的SQL,并保存SQL到Log表中
這篇文章主要介紹了使用SpringAop動(dòng)態(tài)獲取mapper執(zhí)行的SQL,并保存SQL到Log表中問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
@Scheduled 如何讀取動(dòng)態(tài)配置文件
這篇文章主要介紹了@Scheduled 如何讀取動(dòng)態(tài)配置文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
@PropertySource 無(wú)法讀取配置文件的屬性值解決方案
這篇文章主要介紹了@PropertySource 無(wú)法讀取配置文件的屬性值解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
簡(jiǎn)單了解Java方法的定義和使用實(shí)現(xiàn)詳解
這篇文章主要介紹了簡(jiǎn)單了解Java方法的定義和使用實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12

