我有以下酒店数据模型,
public class HotelData {
private String name;
private String address;
private String stars;
private String contact;
private String phone;
private String uri;
public HotelData(String name, String address, String stars, String contact, String phone, String uri) {
this.name = name;
this.address = address;
this.stars = stars;
this.contact = contact;
this.phone = phone;
this.uri = uri;
}
public HotelData() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStars() {
return stars;
}
public void setStars(String stars) {
this.stars = stars;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
并且,我使用以下方法使用List行以JSON格式进行转换。
@Override
public void dataToJsonConverter() {
ObjectMapper mapper = new ObjectMapper();
try {
String jsonInString = "";
for (HotelData hotels : rows) {
jsonInString += mapper.writeValueAsString(hotels);
}
mapper.writeValue(new File(Constant.OUTPUT_LOC + "/result.json"), jsonInString);
// jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(hotelData);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("CONVERTED TO JSON");
}
但是,数据量很大,转换需要几秒钟。我可以使用多线程来加速这个过程吗?我没有很多线程经验,所以,如果问题不合适,请接受道歉。我只想加快数据对话。
更新:令人惊讶的是,StringBuilder
比String
快约25倍。 WOW
答案 0 :(得分:1)
多线程不是不可能的,但会使这种情况大为复杂化。如果方法要复杂,我提出一种方法,开始时更快。 (并没有提供并行解决方案必须处理的行李)
由于ObjectMapper中使用的反射,字符串化无疑是如此之慢。如果您需要额外的编程,下一个解决方案会更快。但它并不是通用的。
public interface JSONNable {
String toJSON();
}
public class HotelData implements JSONNable {
private String name;
private String address;
private String stars;
private String contact;
private String phone;
private String uri;
public HotelData(String name, String address, String stars, String contact, String phone, String uri) {
this.name = name;
this.address = address;
this.stars = stars;
this.contact = contact;
this.phone = phone;
this.uri = uri;
}
public HotelData() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getStars() {
return stars;
}
public void setStars(String stars) {
this.stars = stars;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String toJSON() {
return String.format("{\"name\" : \"%s\", \"address\" : \"%s\", \"stars\" : \"%s\", \"contact\" : \"%s\", \"phone\" : \"%s\", \"uri\" : \"%s\"}",
name, address, stars, contact, phone, uri);
}
/* or any other iterable<HotelData> hotels, including an array */
public static String hotelsToJSON(ArrayList<HotelData> hotels) {
StringBuilder sb = new StringBuilder();
sb.append('[');
for (HotelData hotelData : hotels) {
sb.append(hotel.toJSON());
sb.append(',');
}
sb.insert(sb.length() - 1, ']');
return sb.toString();
}
}
请注意,在创建新接口和实现toJSON()方法时,不必对HotelData Object进行运行时分析(这很慢)。执行时间的差异会花费你额外的编程时间。
答案 1 :(得分:0)
多线程无法加速写入文件操作。您可以加速的唯一事情是数据的JSON转换。您可以通过使用ForkJoinPool或ExecuterService来实现这一点,以便在多个线程之间拆分数据来处理它们。最后,您可以收集JSON字符串,然后将它们写入文件。
在这里您可以找到如何使用ForkJoinPool的教程以及通常如何工作: ForkJoinPool Tutorial
修改
我只有一个排序大数组的例子
在这里你可以看到ForkJoinPool用来对数据和一些辅助方法进行排序的RecursiveTask
// class used to store job results
class SortedArray
{
private int [] array;
public void setArray(int [] array)
{
this.array = array;
}
public int[] getArray()
{
return this.array;
}
}
class Sort extends RecursiveTask<SortedArray>
{
// blocksize that is used to decide whenever insertionsort
// is used or more splits are necessary
static final int BlockSize = 100;
private int lb,ub;
private int [] data;
public Sort(int lb, int ub, int[] data)
{
this.lb = lb;
this.ub = ub;
this.data = data;
}
protected SortedArray compute() {
// if array size is smaller than the blocksize
if((ub - lb) <= BlockSize)
{
// do insertionSort in the segment
insertionSort(this.data, lb, ub);
}
// if array size is bigger than the blocksize
else
{
if(lb+1 < ub){
// compute mid value for split
int mid = (lb+ub)/2;
// create new job for the left segment
Sort left = new Sort(this.lb,mid,this.data);
// create new job for the right segment
Sort right = new Sort(mid,this.ub,this.data);
// wait for the first job
left.fork();
// wait for the second job
right.fork();
// redeem data from the first job
SortedArray arr1 = left.join();
// redeem data from the second job
SortedArray arr2 = right.join();
// merge the data
merge(this.data,lb,mid,ub);
}
}
// create SortedArray object to store result
SortedArray sArr = new SortedArray();
// set result
sArr.setArray(this.data);
// return result
return sArr;
}
// given method
private void insertionSort(int dt[], int a, int b){
for(int i = a; i < b; i++){
int j = i;
while(j > a && dt[j] < dt[j-1]){
int temp = dt[j]; dt[j] = dt[j-1]; dt[j-1] = temp;
j--;
}
}
}
private void merge(int f[], int lb, int mid, int ub){
int c[] = new int[ub-lb];
int k = 0;int j = lb; int h = mid;
while(j < mid && h < ub){
if(f[j] <= f[h]){
c[k] = f[j];
j++;
}
else{
c[k] = f[h];
h++;
}
k++;
}
while(j < mid){ c[k] = f[j]; k++; j++; }
while(h < ub){c[k] = f[h]; k++; h++;}
//Now copy data back to array
for(int p = 0; p < c.length;p++)
f[lb+p] = c[p];
}
}
这里是示例用法
startTime = System.currentTimeMillis();
// create the array
int [] arr = new int [10000000];
for(int i = 0; i< arr.length;i++)
{
// fill the array with random values
arr[i] = (int)(Math.random()*10000000);
}
// create a ForkJoinPool
ForkJoinPool fjPool = new ForkJoinPool();
// invoke the sort and store the result in the SortedArray class
SortedArray sortedArr = fjPool.invoke(new Sort(0, arr.length, arr));
endTime = System.currentTimeMillis();
runningTime = endTime-startTime;
System.out.println("============================================");
System.out.println("Arraysize: " + arr.length);
System.out.printf("ForkJoinpool contains %d Threads\n",fjPool.getPoolSize());
System.out.println("Running time: "+runningTime + " millisecs (" +(runningTime/1000.0) + ") secs");
System.out.println("============================================");
System.out.println();
答案 2 :(得分:-1)
如果转换逻辑花费时间并且您认为写入文件不是开销,那么您可以启动(比方说)n个线程并将totalHotel / n hotels分配给每个要转换的线程。
有两种写入文件的方法。答:每个线程都会写入自己的文件。 B.所有线程都写入单个文件。方法B需要同步,如果你确定写入转换逻辑并不耗时,否则你会在方法B中运行时间变得更糟,如果转换更快并且写入所有线程都在等待当前线程完成写入
如果使用方法A,那么您需要编写新代码来合并文件并相应地处理文件单输出文件的正确前缀和后缀。
class Worker implements Runnable {
public void run() {
}
}
这是基本的worker runnable类,你可以创建如下,并将几个酒店对象传递给它,以便在run
方法中转换为json。
Thread t = new Thread(new Worker());
....
t.start();
在线程t
上调用start之前,您可以通过constuctor或任何其他方法传递任何其他数据。