如果遇到程序中的数据量大时,可以通过以下方法将其进行处理。
方法如下:
1 将得到的数据添加到内存中
2 启动一个线程(一直循环,不断的去扫描),专门读取内存的数据。
3 得到内存中的数据,进行下一步的操作(如添加到redis中或批量操作插入到数据库中)。
示例:
1 通过webservice时或者程序订阅每时每刻都会有大量的数据得到。
2 为了将数据保存到内存中。定义一个线程安全的类(单例模式+虚拟锁),类中定义一个list用来存取数据。
3 当程序中得到数据时,保存到该类的list中(通过虚拟锁达到线程安全)。
4 启动一个子线程(一直循环,不断的去扫描),专门去读取该类的list数据(每次读取1000条,可配置,读取list的方法也是通过虚拟锁达到线程安全)。
5 通过子线程得到了分批次的数据后。可以进行后续操作。如添加到redis中或批量操作插入到数据库中。
具体例子:
1 新建一个类,用来保存数据,将数据保存到内存中。
如:
public class AisHistoryServiceFactory {
public static AisHistoryServiceFactory instance = null;
private static final Object uniqueLock = new Object();
private static final Object objectLock = new Object();
private List<AisInfo> aisInfoList = new ArrayList<AisInfo>();
public static boolean flag_insert_hbase=false;//是否容许插入到hbase中
public static AisHistoryServiceFactory getInstance() {
if (null == instance) {
synchronized (uniqueLock) {
if (null == instance) {
instance = new AisHistoryServiceFactory();
}
}
}
return instance;
}
public boolean addAisInfo(AisInfo info) {
synchronized (objectLock) {
if (isFull()) {
return false; // 内存list满,
}
//不需要解密
AisInfo in = info;//getFromBase64(info);
if (isNeedInfo(in)) {
if (null == aisInfoList) {
aisInfoList = new ArrayList<AisInfo>();
}
if (!aisInfoList.contains(in)) {
aisInfoList.add(0, in);
}
}
return true;
}
}
public boolean getAisInfo(List<AisInfo> list, int size) {
synchronized (objectLock) {
// System.out.println("==== Get Info Size : " + size + " ====");
// System.out.println("==== Info List Size Before Get : " + aisInfoList.size() + "====");
int countNum = 0;
if(null != aisInfoList && aisInfoList.size() > 0){
for (int i = aisInfoList.size() - 1; i >= 0; i--) {
AisInfo temp = aisInfoList.remove(i);
list.add(temp);
countNum++ ;
if(countNum >= size){
// System.out.println("==== Info List Size After Get 1 : " + aisInfoList.size() + "====");
return true;
}
if(aisInfoList.size() <= 0){
// System.out.println("==== Info List Size After Get 2 : " + aisInfoList.size() + "====");
return true;
}
}
}
return false;
}
}
private boolean isNeedInfo(AisInfo info) {
return true;
}
private boolean isFull() {
synchronized (objectLock) {
int maxSize = SystemConfigFactory.getInstance().getSystemConfigInt(ConfigMacroDef.AIS_INFO_MAX_SIZE_WAN, 100); // 保存多少条AIS数据,
maxSize = maxSize * 10000;
if (null == aisInfoList && aisInfoList.size() > maxSize) {
return true;
}
else {
return false;
}
}
}
}
2 程序中得到原始数据后,将其保存到内存中。
如(某个类的普通方法):
public void inserToAISH(AisInfo aisInfo_old) {
//改为加入到内存中
AisHistoryServiceFactory.getInstance().addAisInfo(aisInfo_old);
}
3 程序中启动一个子线程(一直循环,不断的去扫描),用来读取内存中的数据。
如(最好放在启动的servlet中):
new AisHistoryServiceAisThread().start();
子线程类:
public class AisHistoryServiceAisThread extends Thread{
/**
* Description: <br>
*
* @author XXX<br>
* @taskId <br> <br>
*/
@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
try {
Thread.sleep(10 * 1000);
//System.out.println("开始启动读取数据的线程了");
AIS_LOG.INFO("开始启动读取港航局历史轨迹的数据的线程了");
while (true) {
AisHistoryAisFactory.getInstance().addAisDataToHistory();
Thread.sleep(10 * 1000);
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4 子线程会进行得到数据后的操作(分批次的读取数据,每次读取1000条。)。
如(普通类的普通方法,可以弄成单例的):
public class AisHistoryAisFactory {
private int ais_num = 1000;
private static AisHistoryAisFactory webServiceaisFactory = null;
private static AisInfoService aisInfoService = (AisInfoService) SpringBeanFactory.getInstance().getBean(SpringBeanMacroDef.Service.AIS_INFO_SERVICE_IMPL);
private static FerryService ferryService = (FerryService) SpringBeanFactory.getInstance().getBean(SpringBeanMacroDef.Service.FERRY_SERVICE_IMPL);
private AisHistoryAisFactory() {
}
public static AisHistoryAisFactory getInstance() {
if (webServiceaisFactory == null) {
webServiceaisFactory = new AisHistoryAisFactory();
return webServiceaisFactory;
}
else {
return webServiceaisFactory;
}
}
public void addAisDataToHistory() {
//WebServiceAisParseFactory aisParseFactory = WebServiceAisParseFactory.getInstance();
AisInfo aisInfo = new AisInfo();
AisInfo aisInfo_old = null;
List<AisInfo> aisDataList = new ArrayList<AisInfo>();
AisHistoryServiceFactory.getInstance().getAisInfo(aisDataList, ais_num);
int insert_num = 0;
int updata_num = 0;
/* 这是插入到redis中
for (int i = 0; i < aisDataList.size(); i++) {
String aisData = aisDataList.get(i).toString();
//System.out.println(aisData);
aisInfo = aisParseFactory.parseAIS(aisData);
if(aisInfo==null){//为空则不进行保存到redis中
System.out.println("出现解析gis数据错误,拼装为aisInfo时,返回的aisInfo为空,aisData="+aisData);
AIS_LOG.INFO("出现解析gis数据错误,拼装为aisInfo时,返回的aisInfo为空,aisData="+aisData);
}else{//增加操作,放入redis库
RedisFactory.getInstance().setAisInfo(aisInfo);
}
}
AIS_LOG.INFO("插入了:" + aisDataList.size() + "的ais数据");*/
// System.out.println("插入了:"+insert_num+"的ais数据。 更新了:"+updata_num);
//这是进行批操作,插入到数据库中.调用jdbc批处理。
DBCPHelper.batchInsert(aisDataList);
}
}
!!!注意,保存数据的类需要是线程安全的(通过单例+虚拟锁达到线程安全).如上述的AisHistoryServiceFactory类
通过这种方式就可以解决程序中得到大量数据。还需要将其大量数据保存到redis或者数据库中。
!!!注意,读取内存数据时,是分批次读取。如:每次读取1000条数据。
方法如下:
1 将得到的数据添加到内存中
2 启动一个线程(一直循环,不断的去扫描),专门读取内存的数据。
3 得到内存中的数据,进行下一步的操作(如添加到redis中或批量操作插入到数据库中)。
示例:
1 通过webservice时或者程序订阅每时每刻都会有大量的数据得到。
2 为了将数据保存到内存中。定义一个线程安全的类(单例模式+虚拟锁),类中定义一个list用来存取数据。
3 当程序中得到数据时,保存到该类的list中(通过虚拟锁达到线程安全)。
4 启动一个子线程(一直循环,不断的去扫描),专门去读取该类的list数据(每次读取1000条,可配置,读取list的方法也是通过虚拟锁达到线程安全)。
5 通过子线程得到了分批次的数据后。可以进行后续操作。如添加到redis中或批量操作插入到数据库中。
具体例子:
1 新建一个类,用来保存数据,将数据保存到内存中。
如:
public class AisHistoryServiceFactory {
public static AisHistoryServiceFactory instance = null;
private static final Object uniqueLock = new Object();
private static final Object objectLock = new Object();
private List<AisInfo> aisInfoList = new ArrayList<AisInfo>();
public static boolean flag_insert_hbase=false;//是否容许插入到hbase中
public static AisHistoryServiceFactory getInstance() {
if (null == instance) {
synchronized (uniqueLock) {
if (null == instance) {
instance = new AisHistoryServiceFactory();
}
}
}
return instance;
}
public boolean addAisInfo(AisInfo info) {
synchronized (objectLock) {
if (isFull()) {
return false; // 内存list满,
}
//不需要解密
AisInfo in = info;//getFromBase64(info);
if (isNeedInfo(in)) {
if (null == aisInfoList) {
aisInfoList = new ArrayList<AisInfo>();
}
if (!aisInfoList.contains(in)) {
aisInfoList.add(0, in);
}
}
return true;
}
}
public boolean getAisInfo(List<AisInfo> list, int size) {
synchronized (objectLock) {
// System.out.println("==== Get Info Size : " + size + " ====");
// System.out.println("==== Info List Size Before Get : " + aisInfoList.size() + "====");
int countNum = 0;
if(null != aisInfoList && aisInfoList.size() > 0){
for (int i = aisInfoList.size() - 1; i >= 0; i--) {
AisInfo temp = aisInfoList.remove(i);
list.add(temp);
countNum++ ;
if(countNum >= size){
// System.out.println("==== Info List Size After Get 1 : " + aisInfoList.size() + "====");
return true;
}
if(aisInfoList.size() <= 0){
// System.out.println("==== Info List Size After Get 2 : " + aisInfoList.size() + "====");
return true;
}
}
}
return false;
}
}
private boolean isNeedInfo(AisInfo info) {
return true;
}
private boolean isFull() {
synchronized (objectLock) {
int maxSize = SystemConfigFactory.getInstance().getSystemConfigInt(ConfigMacroDef.AIS_INFO_MAX_SIZE_WAN, 100); // 保存多少条AIS数据,
maxSize = maxSize * 10000;
if (null == aisInfoList && aisInfoList.size() > maxSize) {
return true;
}
else {
return false;
}
}
}
}
2 程序中得到原始数据后,将其保存到内存中。
如(某个类的普通方法):
public void inserToAISH(AisInfo aisInfo_old) {
//改为加入到内存中
AisHistoryServiceFactory.getInstance().addAisInfo(aisInfo_old);
}
3 程序中启动一个子线程(一直循环,不断的去扫描),用来读取内存中的数据。
如(最好放在启动的servlet中):
new AisHistoryServiceAisThread().start();
子线程类:
public class AisHistoryServiceAisThread extends Thread{
/**
* Description: <br>
*
* @author XXX<br>
* @taskId <br> <br>
*/
@Override
public void run() {
// TODO Auto-generated method stub
//super.run();
try {
Thread.sleep(10 * 1000);
//System.out.println("开始启动读取数据的线程了");
AIS_LOG.INFO("开始启动读取港航局历史轨迹的数据的线程了");
while (true) {
AisHistoryAisFactory.getInstance().addAisDataToHistory();
Thread.sleep(10 * 1000);
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4 子线程会进行得到数据后的操作(分批次的读取数据,每次读取1000条。)。
如(普通类的普通方法,可以弄成单例的):
public class AisHistoryAisFactory {
private int ais_num = 1000;
private static AisHistoryAisFactory webServiceaisFactory = null;
private static AisInfoService aisInfoService = (AisInfoService) SpringBeanFactory.getInstance().getBean(SpringBeanMacroDef.Service.AIS_INFO_SERVICE_IMPL);
private static FerryService ferryService = (FerryService) SpringBeanFactory.getInstance().getBean(SpringBeanMacroDef.Service.FERRY_SERVICE_IMPL);
private AisHistoryAisFactory() {
}
public static AisHistoryAisFactory getInstance() {
if (webServiceaisFactory == null) {
webServiceaisFactory = new AisHistoryAisFactory();
return webServiceaisFactory;
}
else {
return webServiceaisFactory;
}
}
public void addAisDataToHistory() {
//WebServiceAisParseFactory aisParseFactory = WebServiceAisParseFactory.getInstance();
AisInfo aisInfo = new AisInfo();
AisInfo aisInfo_old = null;
List<AisInfo> aisDataList = new ArrayList<AisInfo>();
AisHistoryServiceFactory.getInstance().getAisInfo(aisDataList, ais_num);
int insert_num = 0;
int updata_num = 0;
/* 这是插入到redis中
for (int i = 0; i < aisDataList.size(); i++) {
String aisData = aisDataList.get(i).toString();
//System.out.println(aisData);
aisInfo = aisParseFactory.parseAIS(aisData);
if(aisInfo==null){//为空则不进行保存到redis中
System.out.println("出现解析gis数据错误,拼装为aisInfo时,返回的aisInfo为空,aisData="+aisData);
AIS_LOG.INFO("出现解析gis数据错误,拼装为aisInfo时,返回的aisInfo为空,aisData="+aisData);
}else{//增加操作,放入redis库
RedisFactory.getInstance().setAisInfo(aisInfo);
}
}
AIS_LOG.INFO("插入了:" + aisDataList.size() + "的ais数据");*/
// System.out.println("插入了:"+insert_num+"的ais数据。 更新了:"+updata_num);
//这是进行批操作,插入到数据库中.调用jdbc批处理。
DBCPHelper.batchInsert(aisDataList);
}
}
!!!注意,保存数据的类需要是线程安全的(通过单例+虚拟锁达到线程安全).如上述的AisHistoryServiceFactory类
通过这种方式就可以解决程序中得到大量数据。还需要将其大量数据保存到redis或者数据库中。
!!!注意,读取内存数据时,是分批次读取。如:每次读取1000条数据。