我理解的是在觀察者方面,在一定情況下慈俯,可以看作是一種事件驅(qū)動(dòng)的形式渤刃。
由對(duì)象的行為觸發(fā),然后執(zhí)行不同的行為驅(qū)動(dòng)方式贴膘,有很好的解耦合性卖子。
/**
* Created by kevin on 17/8/8.
*/
public interface IObserver {
abstract void notifyUser(Message message);
}
/**
* Created by kevin on 17/8/8.
*/
public abstract class AbstractObserver{
protected Message message;
protected abstract void notifyUser(Message message);
}
/**
* Created by kevin on 17/8/8.
*/
public class AObserverImpl extends AbstractObserver {
@Override
public void notifyUser(Message message) {
this.message = message;
this.message.addObserver(this);
System.out.println("A已接收到消息!"+ this.message.getMessage());
}
}
/**
* Created by kevin on 17/8/8.
*/
public class BObserverImpl extends AbstractObserver {
@Override
public void notifyUser(Message message) {
this.message = message;
this.message.addObserver(this);
System.out.println("B已接收到消息!"+this.message.getMessage());
}
}
/**
* Created by kevin on 17/8/8.
*/
public class CObserverImpl extends AbstractObserver {
@Override
public void notifyUser(Message message) {
this.message = message;
this.message.addObserver(this);
System.out.println("C已接收到消息!"+this.message.getMessage());
}
}
/**
* Created by kevin on 17/8/8.
*/
public class Message{
private List<AbstractObserver> observers = new ArrayList<AbstractObserver>();
public void addObserver(AbstractObserver observer){
observers.add(observer);
}
private String message;
public String getMessage(){
return message;
}
public void pushMessage(String message){
this.message = message;
}
public void notifyMessage() {
for(int i = 0; i < observers.size(); i++){
observers.get(i).notifyUser(this);
}
}
}
完全可以模擬這樣的場(chǎng)景,進(jìn)行讀取刑峡,然后訂閱發(fā)布
所以可以將nio通道內(nèi)的數(shù)據(jù)一次分發(fā)給三個(gè)觀察者洋闽,來(lái)模擬觸發(fā)事件
/**
* Created by kevin on 17/8/10.
*/
public class RunThread extends Thread {
private int i;
private MappedByteBuffer mappedByteBuffer;
private int singleCpuPosition;
private FileChannel fileChannel;
public RunThread(int i, MappedByteBuffer mappedByteBuffer, int singleCpuPosition,FileChannel fileChannel ){
this.i = i;
this.mappedByteBuffer = mappedByteBuffer;
this.singleCpuPosition = singleCpuPosition;
this.fileChannel = fileChannel;
}
@Override
public void run() {
//消息
String mes = "";
//定義每次發(fā)送給客戶端(a b c)的數(shù)據(jù)量大小
int len = 50;
//定義byte[]數(shù)組
byte[] bytes = null;
//內(nèi)存映射對(duì)象MappedByteBuffer非常大,但是發(fā)送到客戶端的數(shù)據(jù)是需要分段的
try {
int currentPosition = i*singleCpuPosition;
int currentPosition2 = (i+1)*singleCpuPosition;
if(Runtime.getRuntime().availableProcessors() == i+1) {
currentPosition2 = (int) fileChannel.size();
}
int size = currentPosition2 - currentPosition;
int count = size / len;
int remainder = size % len;
mappedByteBuffer.position((int) currentPosition);
for(int j = 0; j < count; j++){
bytes = new byte[len];
//將buffer中指定位置的信息復(fù)制給bytes
mappedByteBuffer.get(bytes);
mes = new String(bytes);
Message message = new Message();
message.pushMessage(mes);
new AObserverImpl().notifyUser(message);
new BObserverImpl().notifyUser(message);
new CObserverImpl().notifyUser(message);
//設(shè)置偏移量
mappedByteBuffer.position((j+1)*len);
}
if(remainder > 0 ){
byte[] bytes1 = new byte[remainder];
mappedByteBuffer.get(bytes1);
mes = new String(bytes1);
Message message = new Message();
message.pushMessage(mes);
new AObserverImpl().notifyUser(message);
new BObserverImpl().notifyUser(message);
new CObserverImpl().notifyUser(message);
}
mappedByteBuffer.flip();
mappedByteBuffer.clear();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 模擬一套高效的文件讀取工具,文件很大但不超過2g,并將獲取的文件發(fā)送給a b c三人
*
* Created by kevin on 17/8/9.
*/
public class runNio {
public static void main(String[] args) {
try {
//讀取文件
String root = System.getProperty("user.dir");
RandomAccessFile raf = new RandomAccessFile(root+"/src/main/resources/spider.txt","r");
//設(shè)置文件通道
FileChannel fileChannel = raf.getChannel();
//映射整個(gè)文件到該對(duì)象
final MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY,0,fileChannel.size());
//獲取當(dāng)前cpu核心數(shù)目
final int cpus = Runtime.getRuntime().availableProcessors();
//計(jì)算每個(gè)cpu應(yīng)該從什么位置處理
final int singleCpuPosition = (int) (fileChannel.size()/cpus);
//開啟cpus個(gè)線程發(fā)送數(shù)據(jù)
for(int i = 0; i < cpus; i++){
new RunThread(i,mappedByteBuffer,singleCpuPosition,fileChannel).start();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
自定義一個(gè)文件突梦,可以嘗試運(yùn)行