`

单线程大数据量保存方法:thread, 泛型,etc

阅读更多
只是一个简单的思路
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 适用于大数据量的导入操作
 * @author qth
 *
 */
public abstract class SingleThreadSaver {
	
	private Map<String, Long> countHolder = null;
	private List<String> errorMsgHolder = null;
	
	private static final String COUNT_KEY_SUCCESS = "success";
	private static final String COUNT_KEY_ERROR = "error";
	
	private SingleThreadSaverPool pool = null;
	
	public SingleThreadSaver() {
		countHolder = new HashMap<String, Long>();
		countHolder.put(COUNT_KEY_SUCCESS, 0L);
		countHolder.put(COUNT_KEY_ERROR, 0L);
		
		errorMsgHolder = new ArrayList<String>();
		
		pool = SingleThreadSaverPool.getInstance();
	}
	
	public List<String> getErrorMsgList() {
		List<String> ret = new ArrayList<String>();
		ret.addAll(errorMsgHolder);
		return ret;
	}
	
	protected synchronized void increaseSuccessCount() {
		countHolder.put(COUNT_KEY_SUCCESS, 
				countHolder.get(COUNT_KEY_SUCCESS) + 1);
	}
	
	public long getSuccessCount() {
		return countHolder.get(COUNT_KEY_SUCCESS);
	}
	
	protected synchronized void increaseErrorCount() {
		countHolder.put(COUNT_KEY_ERROR, 
				countHolder.get(COUNT_KEY_ERROR) + 1);
	}
	
	public long getErrorCount() {
		return countHolder.get(COUNT_KEY_ERROR);
	}
	
	protected void addErrorMsg(String msg) {
		errorMsgHolder.add(msg);
	}

	public void saveInSingleThread() {
		final Date now = new Date();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					save();
				} catch(Exception e) {
					e.printStackTrace();
					addErrorMsg(e.getMessage());
					increaseErrorCount();
				} finally {
					try {
						pool.releaseSaver(SingleThreadSaver.this);
					} catch(Exception e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	
	
	/**
	 * 单线程执行体
	 */
	protected abstract void save();
}


===========================================
package com.nssc.exam.common;

import java.util.HashMap;
import java.util.Map;

/**
 * 利用线程池管理SingleThreadSaver, 每种Class的SingleThreadSaver同一时间中只允许运行5个
 * @author qth
 *
 */
public final class SingleThreadSaverPool {
	
	private static SingleThreadSaverPool instance = null;
	
	private static Map<Class<? extends SingleThreadSaver>, Map<SingleThreadSaver, Integer>> pool = null;
	
	private static final int POOL_SIZE_DEFAULT = 5;
	private static final Integer STATE_FREE = 0; 
	private static final Integer STATE_BUSY = 1; 
	
	
	private SingleThreadSaverPool() {
		pool = new HashMap<Class<? extends SingleThreadSaver>, 
								Map<SingleThreadSaver,Integer>>();
	}
	
	public static SingleThreadSaverPool getInstance() {
		if(instance == null) {
			instance = new SingleThreadSaverPool();
		}
		
		return instance;
	}
	
	/**
	 * 取得一个空闲的 saver
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	public static <T extends SingleThreadSaver> T getSaver(
			Class<? extends SingleThreadSaver> clazz)
	throws Exception {
		if(instance == null) {
			instance = new SingleThreadSaverPool();
		}
		
		Map<SingleThreadSaver, Integer> subPool = pool.get(clazz);
		
		if(subPool == null || subPool.isEmpty()) {
			subPool = new HashMap<SingleThreadSaver, Integer>();
			
			for(int i = 0; i < POOL_SIZE_DEFAULT; i++) {
				SingleThreadSaver saverTmp = clazz.newInstance();
				subPool.put(saverTmp, STATE_FREE);
			}
			
			pool.put(clazz, subPool);
		}
		
		for(Map.Entry<SingleThreadSaver, Integer> entry : subPool.entrySet()) {
			SingleThreadSaver tmp = entry.getKey();
			if(subPool.get(tmp) == STATE_FREE) {
				subPool.put(tmp, STATE_BUSY);
				return (T)tmp;
			}
		}
		
		//now all 5 are busy
		throw new IllegalStateException("No free saver available, please try later.");
	}
	
	/**
	 * 释放得到的saver
	 * @param <T>
	 * @param saver
	 */
	public static <T extends SingleThreadSaver> void releaseSaver(T saver) 
	throws Exception {
		Map<SingleThreadSaver, Integer> subPool = pool.get(saver.getClass());
		
		if(subPool == null || subPool.isEmpty()) {
			throw new IllegalStateException("The saver passed is not get from pool!");
		}
		
		if(subPool.get(saver) == STATE_FREE) {
			throw new IllegalStateException("Pool is NOT working properly!");
		}
		
		subPool.put(saver, STATE_FREE);
	}
}



===========================================
项目实例:大量照片从文件系统导入数据库
===========================================
import java.io.File;
import java.util.Date;

import com.nssc.exam.common.SingleThreadSaver;
import com.nssc.exam.common.Tools;
import com.nssc.exam.self.model.TStudentPhoto;

public class SelfStudentPhotoSaver extends SingleThreadSaver {
	private IStudentService studentService = null;
	private File folder = null;
	private Date optTime = null;
	private long userId = -1L;
	
	@Override
	public void save() {
		importPhotosUnderThisFolder(folder, optTime, userId);
	}

	
	private void importPhotosUnderThisFolder(File pFolder, Date optTime, long userId) {
		if(pFolder == null || !pFolder.canRead()) {
			return;
		}
		
		if(pFolder.isFile()) {
			try {
				if(!pFolder.getName().toUpperCase().endsWith(".JPG")) {
					return;
				}
				
				String fileName = pFolder.getName().toUpperCase().trim();
				String zkz = fileName.substring(0, fileName.indexOf(".JPG"));
				
				if(zkz.length() > 12) {
					addErrorMsg("准考证不合法:" + zkz + "(" + pFolder.getAbsolutePath() + ")");
					increaseErrorCount();
					return;
				}
				
				TStudentPhoto sp = new TStudentPhoto();
				sp.setZkz(zkz);
				sp.setPhotoContent(Tools.getBytesFromFile(pFolder));
				sp.setOperateTime(optTime);
				sp.setOperateUserId(userId);
				
				if(studentService.uploadStudentPhoto(sp)) {
					increaseSuccessCount();
				} else {
					increaseErrorCount();
				}
				
				return;
			} catch(Exception e) {
				e.printStackTrace();
				addErrorMsg(e.getMessage());
				increaseErrorCount();
				return;
			}
		}
		
		if(pFolder.listFiles() == null) {
			return;
		}
		
		for(File subFolder : pFolder.listFiles()) {
			importPhotosUnderThisFolder(subFolder, optTime, userId);
		}
	}
	
	public static void main(String[] args) 
	throws Exception{
		SelfStudentPhotoSaver saver = SelfStudentPhotoSaver.class.newInstance();
		System.out.println(saver);
	}

	public IStudentService getStudentService() {
		return studentService;
	}

	public void setStudentService(IStudentService studentService) {
		this.studentService = studentService;
	}

	public File getFolder() {
		return folder;
	}

	public void setFolder(File folder) {
		this.folder = folder;
	}

	public Date getOptTime() {
		return optTime;
	}

	public void setOptTime(Date optTime) {
		this.optTime = optTime;
	}

	public long getUserId() {
		return userId;
	}

	public void setUserId(long userId) {
		this.userId = userId;
	}
}
分享到:
评论

相关推荐

    VC++ 2005:泛型编程

    在C++/CLI中声明泛型类或方法时,使用`generic &lt;typename T&gt;`关键字,其中`T`是类型参数。例如,可以创建一个泛型栈`Stack`,如下所示: ```cpp generic ref class Stack { public: void Push(ItemType item) {…}...

    C++设计新思维:泛型编程与设计模式之应用.pdf 带目录书签

    C++设计新思维:泛型编程与设计模式之应用.pdf 带目录书签

    C#2.0 锐利体验系列课程(1):泛型编程

    7. 高级泛型:课程还将涉及一些高级泛型主题,如协变和逆变、泛型接口的继承以及泛型的嵌套。这些特性使得泛型能适应更复杂的编程场景。 8. 示例与实践:为了帮助学员更好地掌握泛型,课程会结合大量实例进行教学,...

    C++设计新思维:泛型编程与设计模式之应用

    2. 线程同步:掌握互斥量(mutexes)、条件变量(condition variables)、信号量(semaphores)等同步机制,防止数据竞争和死锁。 3. 并发容器与算法:了解并发安全的容器(如std::vector, std::queue)和并发安全的...

    C#泛型类、泛型方法、泛型接口、泛型委托的实例

    泛型方法允许我们在单个方法中处理多种数据类型。方法内的类型参数与类的类型参数类似,只是它们仅限于该方法的范围。下面的例子展示了一个返回两个参数最大值的泛型方法: ```csharp public static T MaxValue(T a...

    Java 理论和实践 了解泛型

    6. 级联泛型:如`List&lt;List&lt;String&gt;&gt;`表示列表的元素是字符串列表。 7. 类型推断:Java编译器可以根据上下文自动推断类型参数,例如在lambda表达式和方法引用中。 8. 对于数组,由于历史原因,Java的泛型不支持...

    C++设计新思维:泛型编程与设计模式之应用(PDF)

    泛型编程是C++设计哲学的一个重要组成部分,它通过模板机制允许程序员编写与数据类型无关的代码,这种设计使得编写的代码不仅可以复用,而且在面对不同类型的数据时也具有更好的灵活性。在《C++设计新思维》中,作者...

    泛型,泛型擦除,桥接方法

    "泛型、泛型擦除、桥接方法" 泛型是一种类型参数化技术,允许开发者在编写代码时指定类型,提高代码的灵活性和可重用性。泛型可以应用于接口、类和方法中,称之为泛型接口、泛型类和泛型方法。 泛型接口是指在接口...

    c#泛型类、泛型方法、泛型接口、泛型委托

    泛型主要分为四个关键部分:泛型类、泛型方法、泛型接口和泛型委托。下面将详细介绍这四个方面。 1. 泛型类: 泛型类是具有一个或多个类型参数的类。这些类型参数是占位符,代表一种未知的数据类型,直到在创建类...

    c#方法异常和泛型

    在C#编程中,方法异常和泛型是两个至关重要的概念。它们构成了C#语言功能的核心部分,并在软件开发中发挥着关键作用。理解和熟练掌握这两个主题,将有助于提升你的编程技能,无论你是初学者还是有经验的开发者。 ...

    编程选择题40道:泛型:类型安全与泛型编程.Tex.docx

    编程选择题40道:泛型:类型安全与泛型编程.Tex.docx

    关于java基础的泛型的练习

    - 方法级别的泛型:如`public &lt;E&gt; void printList(E[] elements)`,方法内的E仅在此方法内有效。 - 泛型通配符:例如`?`,表示任意类型。`List&lt;?&gt;`表示可以容纳任何类型的列表。 - 上界通配符:`&lt;? extends T&gt;`...

    C++ 设计新思维:泛型编程与设计模式之应用

    C++ 设计新思维:泛型编程与设计模式之应用C++ 设计新思维:泛型编程与设计模式之应用C++ 设计新思维:泛型编程与设计模式之应用C++ 设计新思维:泛型编程与设计模式之应用C++ 设计新思维:泛型编程与设计模式之应用

    SUN公司Java泛型编程文档

    首先,泛型的基本概念是允许在定义类、接口和方法时使用类型参数,这样就可以在编译时检查类型安全,并且可以重用相同的代码处理不同的数据类型。例如,ArrayList是一个典型的泛型类,它可以被声明为ArrayList或...

    泛型+反射:泛型 笔记 ,课后作业

    泛型+反射:泛型 笔记 ,课后作业

    Java基础篇:泛型.pdf

    泛型是Java编程语言中用于减少类型转换错误和增强代码安全性的机制,它允许在定义类、接口和方法时使用类型参数。通过这种方式,可以在编译时期捕获那些只有在运行时期才会暴露的类型错误,提高了代码的健壮性。 ...

    【Flutter】Dart 泛型 ( 泛型类 泛型方法 特定类型约束的泛型 ).zip

    【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 ) https://hanshuliang.blog.csdn.net/article/details/114059611 博客源码快照

    C# 2.0中泛型编程思想分析

    泛型允许开发者定义通用的数据结构和方法,而不必为每种特定的数据类型创建单独的类或接口。这使得代码更加简洁、高效,同时也避免了类型转换带来的潜在错误和性能损失。 在C#中,泛型类定义时,使用尖括号`&lt;T&gt;`来...

Global site tag (gtag.js) - Google Analytics