`

单线程大数据量保存方法: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;
	}
}
分享到:
评论

相关推荐

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

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

    VC++ 2005:泛型编程

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

    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#泛型类、泛型方法、泛型接口、泛型委托

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

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

    泛型编程是C++的重要组成部分,它允许编写不依赖于特定数据类型的代码,从而提高了代码的复用性和灵活性。在书中,作者将详细介绍模板这一泛型编程的主要工具,包括函数模板、类模板、模板特化以及模板元编程等概念...

    c#方法异常和泛型

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

    关于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;`来...

    泛型笔记学习2009

    泛型是Java语言的一项重要特性,它极大提升了代码的类型安全性和可读性,同时也为开发人员提供了一种更为灵活的方式来处理不同类型的数据。通过合理使用泛型,可以有效地避免常见的类型转换错误,并且编写出更加健壮...

Global site tag (gtag.js) - Google Analytics