在寫代碼之前,我們先來想想兩個問題:
- 什麼是異步查詢?
- wait,notify有什麼作用?
首先來說說 “什麼是異步查詢” :
在之前的世紀中,大多數項目都還是單體應用,并且很少會用到多線程,而且在jdk1.5之前線程效率并不高,是以大多數都還是用的同步,很少會很用異步.
異步查詢指的是: 開啟另外一條線程去資料庫裡面查詢資料,而主線程則做一些别的操作,比如說 伺服器端收到用戶端的查詢請求,首先會經過controller層,controller層分發給service層,在service層中,開啟另外一條線程進行資料庫查詢,主線程則記錄相關操作寫入日志.
第二個問題: wait,notify有什麼作用;
wait,notify作用是用于線程直接的通信的
線程通信概念: 線程是作業系統中獨立的個體,但這些個體如果不經過特殊的處理就不能成為一個整體,線程間的通信就成為整體的必用方式之一.當線程存在通信指揮,系統間的互動性會更強大,在提高cpu使用率的同時還會使開發人員對線程任務在處理的過程中進行有效的把控與監督.
1.使用wait/notify方法實作線程間的通信.(注意的是這兩個方法都是object的類的方法,換句話說java為所有的對象都提供了這兩個方法)
2.wait和notify都必須要配合synchronized關鍵字使用
3.wait方法會釋放鎖,而notify方法不釋放鎖
當線程調用notify()方法後,不會立即結束該線程,而是會繼續執行目前線程的方法,隻有當調用notify()方法的線程也就是目前線程,隻有執行完所有操作後才會切換到另一條線程去執行.
還有一種通信方法是利用java提供的api: CountDownLatch
利用CountDownLatch類進行通信,CountDownLatch通信不是利用的鎖,而是根本沒有鎖,wait/notify是需要配合synchronized關鍵字使用的,是具有鎖的.
差別在于: CountDownLatch不具有同步性,它隻是用于線程通信,當線程調用CountDownLatch的await()方法後,調用該方法的線程等待,當另一條線程調用CountDownLatch的countDown方法後直接通知另一條線程開始工作,當另一條線程工作完後,轉到調用CountDownLatch方法的線程繼續進行所有操作
代碼如下:
controller層:
## controller層:
@RequestMapping("/")
public List<TbItem> asyncSelectAll(){
List<TbItem> tbItems = tbItemService.asyncSelectAll();
return tbItems;
}
service層:
## service層:
@Override
public List<TbItem> asyncSelectAll(){
final FutureData futureData = new FutureData();
double time = System.currentTimeMillis();
new Thread(() -> {
futureData.setResult(tbItemMapper.selectAll());
System.out.println(Thread.currentThread().getName());
}).start();
System.out.println(System.currentTimeMillis()-time + Thread.currentThread().getName());
return (List<TbItem>)futureData.getResult();
}
FutureData類:
## FutureData類:
public class FutureData {
private Object result;
private CountDownLatch countDownLatch = new CountDownLatch(1);
//synchronized
public void setResult(Object result){
this.result = result;
if (null == result){
return;
}
countDownLatch.countDown();
//nofity();
}
//synchronized
public Object getResult(){
if (null == result){
try {
countDownLatch.await();
//wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result;
}
}