xiatian 5 lat temu
commit
17d665d5ab
28 zmienionych plików z 2638 dodań i 0 usunięć
  1. 20 0
      .gitignore
  2. 184 0
      pom.xml
  3. 37 0
      src/main/java/cn/com/qmth/Application.java
  4. 11 0
      src/main/java/cn/com/qmth/F.java
  5. 44 0
      src/main/java/cn/com/qmth/RedisConfig.java
  6. 5 0
      src/main/java/cn/com/qmth/S.java
  7. 77 0
      src/main/java/cn/com/qmth/SpringContextHolder.java
  8. 18 0
      src/main/java/cn/com/qmth/Temp.java
  9. 94 0
      src/main/java/cn/com/qmth/importpaper/DateUtil.java
  10. 220 0
      src/main/java/cn/com/qmth/importpaper/FileUtil.java
  11. 58 0
      src/main/java/cn/com/qmth/importpaper/FormFilePart.java
  12. 115 0
      src/main/java/cn/com/qmth/importpaper/HttpMethod.java
  13. 147 0
      src/main/java/cn/com/qmth/importpaper/ImportPaper.java
  14. 53 0
      src/main/java/cn/com/qmth/importpaper/JsonUtil.java
  15. 289 0
      src/main/java/cn/com/qmth/importpaper/OKHttpUtil.java
  16. 79 0
      src/main/java/cn/com/qmth/importpaper/ReWriteExcel.java
  17. 285 0
      src/main/java/cn/com/qmth/importpaper/Temp.java
  18. 172 0
      src/main/java/cn/com/qmth/importpaper/Temp2.java
  19. 104 0
      src/main/java/cn/com/qmth/multithread/Basket.java
  20. 78 0
      src/main/java/cn/com/qmth/multithread/ComputeConsumer.java
  21. 72 0
      src/main/java/cn/com/qmth/multithread/ComputeProducer.java
  22. 62 0
      src/main/java/cn/com/qmth/multithread/Consumer.java
  23. 10 0
      src/main/java/cn/com/qmth/multithread/EndObject.java
  24. 30 0
      src/main/java/cn/com/qmth/multithread/Kv.java
  25. 138 0
      src/main/java/cn/com/qmth/multithread/Producer.java
  26. 80 0
      src/main/java/cn/com/qmth/multithread/StatusException.java
  27. 124 0
      src/main/resources/application.properties
  28. 32 0
      src/main/resources/log4j2.xml

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+*.class
+
+# Proguard folder generated by ide
+.project
+.classpath
+.settings
+target/
+.idea/
+*.iml
+
+# Log Files
+*.log
+*.class
+
+
+# Package Files #
+*.jar
+*.war
+*.ear
+logs/

+ 184 - 0
pom.xml

@@ -0,0 +1,184 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>import-data</groupId>
+	<artifactId>import-data</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<properties>
+		<sonar.jdbc.username>root</sonar.jdbc.username>
+		<java.version>1.8</java.version>
+		<spring-boot.version>2.1.13.RELEASE</spring-boot.version>
+		<druid.version>1.1.14</druid.version>
+		<sonar.jdbc.password>root</sonar.jdbc.password>
+		<sonar.jdbc.url>jdbc:mysql://192.168.10.30:3306/sonar</sonar.jdbc.url>
+		<sonar.host.url>http://192.168.10.30:8080</sonar.host.url>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<examcloud.version>2019-SNAPSHOT</examcloud.version>
+		<sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
+	</properties>
+	<dependencies>
+		<!-- https://mvnrepository.com/artifact/com.ibm.icu/icu4j -->
+		<dependency>
+			<groupId>com.ibm.icu</groupId>
+			<artifactId>icu4j</artifactId>
+			<version>65.1</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-annotations</artifactId>
+			<version>2.9.10</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-core</artifactId>
+			<version>2.9.10</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>2.9.10.3</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.dataformat</groupId>
+			<artifactId>jackson-dataformat-avro</artifactId>
+			<version>2.9.10</version>
+		</dependency>
+		<dependency>
+			<groupId>com.oracle</groupId>
+			<artifactId>ojdbc6</artifactId>
+			<version>11.2.0.4.0-atlassian-hosted</version>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>8.0.17</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-1.2-api</artifactId>
+			<version>2.3</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi</artifactId>
+			<version>3.17</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>3.17</version>
+		</dependency>
+		<dependency>
+			<groupId>com.squareup.okhttp3</groupId>
+			<artifactId>okhttp</artifactId>
+			<version>3.11.0</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<version>23.0</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+			<version>2.5</version>
+		</dependency>
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>2.8.5</version>
+		</dependency>
+		<dependency>
+			<groupId>net.freeutils</groupId>
+			<artifactId>jcharset</artifactId>
+			<version>2.0</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
+		<dependency>
+			<groupId>org.apache.httpcomponents</groupId>
+			<artifactId>httpclient</artifactId>
+			<version>4.5.10</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-redis</artifactId>
+			<version>2.1.13.RELEASE</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+					<testFailureIgnore>true</testFailureIgnore>
+					<skipTests>true</skipTests>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+					<compilerArgument>-proc:none</compilerArgument>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-source-plugin</artifactId>
+				<configuration>
+					<attach>true</attach>
+				</configuration>
+				<executions>
+					<execution>
+						<phase>compile</phase>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<version>2.6</version>
+				<configuration>
+					<archive>
+						<manifest>
+							<addClasspath>true</addClasspath>
+							<classpathPrefix>lib/</classpathPrefix>
+							<mainClass>cn.com.qmth.export.Export</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-dependency-plugin</artifactId>
+				<version>2.10</version>
+				<executions>
+					<execution>
+						<id>copy-dependencies</id>
+						<phase>package</phase>
+						<goals>
+							<goal>copy-dependencies</goal>
+						</goals>
+						<configuration>
+							<outputDirectory>${project.build.directory}/lib</outputDirectory>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

+ 37 - 0
src/main/java/cn/com/qmth/Application.java

@@ -0,0 +1,37 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-16 15:00:21.
+ * *************************************************
+ */
+
+package cn.com.qmth;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@EnableAsync
+@SpringBootApplication
+@ComponentScan(basePackages = {"cn.com.qmth"})
+@EntityScan(basePackages = {"cn.com.qmth"})
+public class Application {
+
+    static {
+        String runtimeLevel = System.getProperty("log.commonLevel");
+        if (null == runtimeLevel) {
+            System.setProperty("log.commonLevel", "INFO");
+        }
+        System.setProperty("hibernate.dialect.storage_engine", "innodb");
+    }
+
+    public static void main(String[] args) {
+        //SpringApplication.run(ApiApplication.class, args);
+    	SpringApplication.run(Application.class, args);
+    	Temp temp=SpringContextHolder.getBean("temp", Temp.class);
+    	temp.test();
+    }
+
+}

+ 11 - 0
src/main/java/cn/com/qmth/F.java

@@ -0,0 +1,11 @@
+package cn.com.qmth;
+
+
+public abstract class F {
+    public void to() {
+        mo();
+    }
+    public void mo() {
+        System.out.println("F mo");
+    }
+}

+ 44 - 0
src/main/java/cn/com/qmth/RedisConfig.java

@@ -0,0 +1,44 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-08-02 09:21:53.
+ * *************************************************
+ */
+
+package cn.com.qmth;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @author: fengdesheng
+ * @since: 2018/8/2
+ */
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> strRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        Jackson2JsonRedisSerializer<?> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+        jacksonSerializer.setObjectMapper(objectMapper);
+        redisTemplate.setValueSerializer(jacksonSerializer);
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+}

+ 5 - 0
src/main/java/cn/com/qmth/S.java

@@ -0,0 +1,5 @@
+package cn.com.qmth;
+
+
+public class S extends F{
+}

+ 77 - 0
src/main/java/cn/com/qmth/SpringContextHolder.java

@@ -0,0 +1,77 @@
+package cn.com.qmth;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.ResolvableType;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring context holder.
+ *
+ * @author WANGWEI
+ * @date 2018年7月10日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+@Component
+public class SpringContextHolder implements ApplicationContextAware {
+
+	private static ApplicationContext ctx = null;
+
+	@Override
+	public void setApplicationContext(ApplicationContext ctx) {
+		SpringContextHolder.ctx = ctx;
+	}
+
+	public static ApplicationContext getApplicationContext() {
+		return ctx;
+	}
+
+	public static Object getBean(String name) {
+		return ctx.getBean(name);
+	}
+
+	public static <T> T getBean(String name, Class<T> requiredType) {
+		return ctx.getBean(name, requiredType);
+	}
+
+	public static <T> T getBean(Class<T> requiredType) {
+		return ctx.getBean(requiredType);
+	}
+
+	public static Object getBean(String name, Object... args) {
+		return ctx.getBean(name, args);
+	}
+
+	public static <T> T getBean(Class<T> requiredType, Object... args) {
+		return ctx.getBean(requiredType, args);
+	}
+
+	public static boolean containsBean(String name) {
+		return ctx.containsBean(name);
+	}
+
+	public static boolean isSingleton(String name) {
+		return ctx.isSingleton(name);
+	}
+
+	public static boolean isPrototype(String name) {
+		return ctx.isPrototype(name);
+	}
+
+	public static boolean isTypeMatch(String name, ResolvableType typeToMatch) {
+		return ctx.isTypeMatch(name, typeToMatch);
+	}
+
+	public static boolean isTypeMatch(String name, Class<?> typeToMatch) {
+		return ctx.isTypeMatch(name, typeToMatch);
+	}
+
+	public static Class<?> getType(String name) {
+		return ctx.getType(name);
+	}
+
+	public static String[] getAliases(String name) {
+		return ctx.getAliases(name);
+	}
+
+}

+ 18 - 0
src/main/java/cn/com/qmth/Temp.java

@@ -0,0 +1,18 @@
+package cn.com.qmth;
+
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+@Component("temp")
+public class Temp {
+	@Autowired
+	private RedisTemplate<String, Object> redisTemplate;
+	
+	public void test() {
+		redisTemplate.opsForValue().set("test9527", "test9527val",1,TimeUnit.MILLISECONDS);
+		System.out.println(redisTemplate.opsForValue().get("test9527"));
+	}
+}

+ 94 - 0
src/main/java/cn/com/qmth/importpaper/DateUtil.java

@@ -0,0 +1,94 @@
+package cn.com.qmth.importpaper;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 日期工具
+ * 
+ * @author WANGWEI
+ */
+public class DateUtil {
+
+	/**
+	 * patterns describing the date and time format
+	 *
+	 * @author WANGWEI
+	 */
+	public interface DatePatterns {
+		public static final String DEFAULT = "yyyyMMddHHmmss";
+
+		public static final String YYYY = "yyyy";
+
+		public static final String YYYYMM = "yyyyMM";
+
+		public static final String YYYYMMDD = "yyyyMMdd";
+
+		public static final String YYYYMMDDHH = "yyyyMMddHH";
+
+		public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";
+
+		public static final String ISO = "yyyy-MM-dd HH:mm:ss";
+
+		public static final String YYYY_MM = "yyyy-MM";
+
+		public static final String YYYY_MM_DD = "yyyy-MM-dd";
+
+		public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
+
+		public static final String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
+	}
+
+	/**
+	 * get now date.
+	 * 
+	 * @param pattern
+	 * @return
+	 */
+	public static String getNow(String pattern) {
+		return format(new Date(), pattern);
+	}
+
+	/**
+	 * get now ISO date.
+	 * 
+	 * @return
+	 */
+	public static String getNowISO() {
+		return format(new Date(), DatePatterns.ISO);
+	}
+
+	/**
+	 * format date.
+	 * 
+	 * @param date
+	 * @param pattern
+	 * @return
+	 */
+	public static String format(Date date, String pattern) {
+		try {
+			SimpleDateFormat df = new SimpleDateFormat(pattern);
+			return df.format(date);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * parse date.
+	 * 
+	 * @param source
+	 * @param pattern
+	 * @return
+	 */
+	public static Date parse(String source, String pattern) {
+		SimpleDateFormat df = new SimpleDateFormat(pattern);
+		try {
+			return df.parse(source);
+		} catch (ParseException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}

+ 220 - 0
src/main/java/cn/com/qmth/importpaper/FileUtil.java

@@ -0,0 +1,220 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-12 15:31:10.
+ * *************************************************
+ */
+
+package cn.com.qmth.importpaper;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+
+
+public class FileUtil {
+    private static Logger log = Logger.getLogger(FileUtil.class);
+
+
+    /**
+     * 解压文件
+     *
+     * @param targetDir 解压目录
+     * @param zipFile   待解压的ZIP文件
+     */
+    public static List<File> unZip(File targetDir, File zipFile) {
+        if (targetDir == null) {
+            log.error("解压目录不能为空!");
+            return null;
+        }
+
+        if (zipFile == null) {
+            log.error("待解压的文件不能为空!");
+            return null;
+        }
+
+        if (!zipFile.exists()) {
+            log.error("待解压的文件不存在!" + zipFile.getAbsolutePath());
+            return null;
+        }
+
+        String zipName = zipFile.getName().toLowerCase();
+        if (zipFile.isDirectory() || zipName.indexOf(".zip") < 0) {
+            log.error("待解压的文件格式错误!");
+            return null;
+        }
+
+        if (!targetDir.exists()) {
+            targetDir.mkdir();
+        }
+
+        log.info("UnZip targetDir:" + targetDir.getAbsolutePath());
+        List<File> result = new LinkedList<>();
+
+        try (ZipFile zip = new ZipFile(zipFile, Charset.forName("UTF-8"));) {
+
+            @SuppressWarnings("rawtypes")
+			Enumeration entries = zip.entries();
+            while (entries.hasMoreElements()) {
+                ZipEntry entry = (ZipEntry) entries.nextElement();
+
+                //Linux中需要替换掉路径的反斜杠
+                String entryName = (File.separator + entry.getName()).replaceAll("\\\\", "/");
+                log.info("UnZip:" + entryName);
+
+                String filePath = targetDir.getAbsolutePath() + entryName;
+                File target = new File(filePath);
+                if (entry.isDirectory()) {
+                    target.mkdirs();
+                } else {
+                    File dir = target.getParentFile();
+                    if (!dir.exists()) {
+                        dir.mkdirs();
+                    }
+
+                    try (OutputStream os = new FileOutputStream(target);
+                         InputStream is = zip.getInputStream(entry);) {
+                        IOUtils.copy(is, os);
+                        os.flush();
+                    } catch (IOException e) {
+                        log.error(e.getMessage(), e);
+                    }
+                    result.add(target);
+                }
+            }
+
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+
+        return result;
+    }
+
+    /**
+     * 文件压缩
+     *
+     * @param target  目录或文件
+     * @param zipFile 压缩后的ZIP文件
+     */
+    public static boolean doZip(File target, File zipFile) {
+        if (target == null || !target.exists()) {
+            log.error("目录或文件不能为空!");
+            return false;
+        }
+
+        if (zipFile == null) {
+            log.error("待压缩的文件不能为空!");
+            return false;
+        }
+
+        try (
+                OutputStream outStream = new FileOutputStream(zipFile);
+                ZipOutputStream zipOutStream = new ZipOutputStream(outStream, Charset.forName("UTF-8"));
+        ) {
+            if (!zipFile.exists()) {
+                boolean ok = zipFile.createNewFile();
+                if (!ok) {
+                    log.error("压缩的文件创建失败!");
+                    return false;
+                }
+            }
+
+            if (target.isDirectory()) {
+                File[] files = target.listFiles();
+                if (files.length == 0) {
+                    log.error("文件夹内未找到任何文件!");
+                    return false;
+                }
+
+                for (File file : files) {
+                    doZip(zipOutStream, file, null);
+                }
+            } else {
+                doZip(zipOutStream, target, null);
+            }
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+
+        return true;
+    }
+
+    private static void doZip(ZipOutputStream zipOutStream, File target, String parentDir) throws IOException {
+        //log.info("Zip:" + parentDir);
+        if (parentDir == null) {
+            parentDir = "";
+        }
+
+        if (!"".equals(parentDir) && !parentDir.endsWith(File.separator)) {
+            parentDir += File.separator;
+        }
+
+        if (target.isDirectory()) {
+            File[] files = target.listFiles();
+            if (files.length > 0) {
+                for (File file : files) {
+                    doZip(zipOutStream, file, parentDir + target.getName());
+                }
+            } else {
+                zipOutStream.putNextEntry(new ZipEntry(parentDir + target.getName()));
+                zipOutStream.closeEntry();
+            }
+        } else {
+            try (InputStream is = new FileInputStream(target);) {
+                zipOutStream.putNextEntry(new ZipEntry(parentDir + target.getName()));
+                int len;
+                byte[] bytes = new byte[1024];
+                while ((len = is.read(bytes)) > 0) {
+                    zipOutStream.write(bytes, 0, len);
+                }
+            } catch (IOException e) {
+                log.error(e.getMessage(), e);
+            }
+            zipOutStream.closeEntry();
+        }
+    }
+    public static boolean doZip(List<File> source, File zipFile) {
+        if (source == null || source.size()==0) {
+            log.error("待压缩的文件不能为空!");
+            return false;
+        }
+
+        if (zipFile == null) {
+            log.error("压缩后的文件不能为空!");
+            return false;
+        }
+
+        try (
+                OutputStream outStream = new FileOutputStream(zipFile);
+                ZipOutputStream zipOutStream = new ZipOutputStream(outStream, Charset.forName("UTF-8"));
+        ) {
+            if (!zipFile.exists()) {
+                boolean ok = zipFile.createNewFile();
+                if (!ok) {
+                    log.error("压缩的文件创建失败!");
+                    return false;
+                }
+            }
+            for (File file : source) {
+                doZip(zipOutStream, file, null);
+            }
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+
+        return true;
+    }
+}

+ 58 - 0
src/main/java/cn/com/qmth/importpaper/FormFilePart.java

@@ -0,0 +1,58 @@
+package cn.com.qmth.importpaper;
+
+import java.io.File;
+
+/**
+ * 表单文件参数
+ *
+ * @author WANGWEI
+ * @date 2019年5月9日
+ * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
+ */
+public class FormFilePart {
+
+	private String paramName;
+
+	private String filename;
+
+	private File file;
+
+	/**
+	 * 构造函数
+	 *
+	 * @param paramName
+	 * @param filename
+	 * @param file
+	 */
+	public FormFilePart(String paramName, String filename, File file) {
+		super();
+		this.paramName = paramName;
+		this.filename = filename;
+		this.file = file;
+	}
+
+	public String getParamName() {
+		return paramName;
+	}
+
+	public void setParamName(String paramName) {
+		this.paramName = paramName;
+	}
+
+	public String getFilename() {
+		return filename;
+	}
+
+	public void setFilename(String filename) {
+		this.filename = filename;
+	}
+
+	public File getFile() {
+		return file;
+	}
+
+	public void setFile(File file) {
+		this.file = file;
+	}
+
+}

+ 115 - 0
src/main/java/cn/com/qmth/importpaper/HttpMethod.java

@@ -0,0 +1,115 @@
+package cn.com.qmth.importpaper;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HTTP method
+ *
+ * @author WANGWEI
+ * @date 2019年4月10日
+ * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
+ */
+public class HttpMethod {
+
+	public static final HttpMethod OPTIONS = new HttpMethod("OPTIONS");
+
+	public static final HttpMethod GET = new HttpMethod("GET");
+
+	public static final HttpMethod HEAD = new HttpMethod("HEAD");
+
+	public static final HttpMethod POST = new HttpMethod("POST");
+
+	public static final HttpMethod PUT = new HttpMethod("PUT");
+
+	public static final HttpMethod PATCH = new HttpMethod("PATCH");
+
+	public static final HttpMethod DELETE = new HttpMethod("DELETE");
+
+	public static final HttpMethod TRACE = new HttpMethod("TRACE");
+
+	public static final HttpMethod CONNECT = new HttpMethod("CONNECT");
+
+	private static final Map<String, HttpMethod> METHOD_MAP = new HashMap<String, HttpMethod>();
+
+	static {
+		METHOD_MAP.put(OPTIONS.toString(), OPTIONS);
+		METHOD_MAP.put(GET.toString(), GET);
+		METHOD_MAP.put(HEAD.toString(), HEAD);
+		METHOD_MAP.put(POST.toString(), POST);
+		METHOD_MAP.put(PUT.toString(), PUT);
+		METHOD_MAP.put(PATCH.toString(), PATCH);
+		METHOD_MAP.put(DELETE.toString(), DELETE);
+		METHOD_MAP.put(TRACE.toString(), TRACE);
+		METHOD_MAP.put(CONNECT.toString(), CONNECT);
+	}
+
+	private final String name;
+
+	/**
+	 * 构造函数
+	 *
+	 * @param name
+	 */
+	private HttpMethod(String name) {
+		if (name == null) {
+			throw new NullPointerException("name");
+		}
+
+		name = name.trim();
+		if (name.length() == 0) {
+			throw new IllegalArgumentException("empty name");
+		}
+
+		for (int i = 0; i < name.length(); i++) {
+			if (Character.isISOControl(name.charAt(i)) || Character.isWhitespace(name.charAt(i))) {
+				throw new IllegalArgumentException("invalid character in name");
+			}
+		}
+
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public static HttpMethod valueOf(String name) {
+		if (name == null) {
+			throw new NullPointerException("name");
+		}
+
+		name = name.trim();
+		if (name.length() == 0) {
+			throw new IllegalArgumentException("empty name");
+		}
+
+		HttpMethod result = METHOD_MAP.get(name);
+		if (result != null) {
+			return result;
+		} else {
+			throw new IllegalArgumentException("undefined name");
+		}
+	}
+
+	@Override
+	public int hashCode() {
+		return getName().hashCode();
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (!(o instanceof HttpMethod)) {
+			return false;
+		}
+
+		HttpMethod that = (HttpMethod) o;
+		return getName().equals(that.getName());
+	}
+
+	@Override
+	public String toString() {
+		return getName();
+	}
+
+}

+ 147 - 0
src/main/java/cn/com/qmth/importpaper/ImportPaper.java

@@ -0,0 +1,147 @@
+package cn.com.qmth.importpaper;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import okhttp3.Response;
+
+public class ImportPaper {
+
+    private static Logger logger = LogManager.getLogger(ImportPaper.class);
+
+    private static String sourceDir = "C:\\Users\\chenken\\Desktop\\temp\\excelDir";
+
+    private static String sourceQuesDir = sourceDir + "\\quesDir\\";
+
+    private final static String url = "http://localhost:8008/api/ecs_ques/importDdCollegePaper";
+
+    private final static String rootOrgId = "7";
+
+    private final static String key = "U_C_7_56368";
+
+    private final static String token = "cafce76e5fae4cbba1fba6bb2e3838fc";
+
+    public static void main(String[] args) {
+        logger.debug("**********************导入开始");
+        Date start = new Date();
+        int errnum = 0;
+        int num = 0;
+        StringBuilder sb = new StringBuilder();
+        // String fname = null;
+        // File dir = new File(sourceDir);
+        // for (File f : dir.listFiles()) {
+        // fname = f.getName();
+        // if (!f.isDirectory() && fname.endsWith(".xlsx")) {
+        // num++;
+        // Date n = new Date();
+        // try {
+        // importCoursePaper(f);
+        // Date et = new Date();
+        // logger.debug("导入成功(" + num + "):" + fname + " 耗时:" + (et.getTime() -
+        // n.getTime()));
+        // } catch (Exception e) {
+        // errnum++;
+        // sb.append(fname).append(",");
+        // Date et = new Date();
+        // logger.error(
+        // "导入失败(" + num + "):" + fname + " 耗时:" + (et.getTime() - n.getTime())
+        // + " " + e.getMessage(),
+        // e);
+        // }
+        // }
+        // }
+
+        try {
+            importCoursePaper(new File("C:\\Users\\chenken\\Desktop\\temp\\excelDir\\F13020020.xlsx"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        Date end = new Date();
+        logger.debug("**********************导入结束  耗时:" + (end.getTime() - start.getTime()));
+
+        logger.debug("**********************导入出错数:" + errnum);
+        logger.debug("**********************导入出错课程:" + sb.toString());
+    }
+
+    private static void importCoursePaper(File file) throws Exception {
+        File zfile = new File(sourceDir + "\\" + file.getName().split("\\.")[0] + ".zip");
+        try {
+            if (zfile.exists()) {
+                zfile.delete();
+            }
+            createZip(file, zfile);
+            submitZip(zfile);
+        } finally {
+            if (zfile.exists()) {
+                zfile.delete();
+            }
+        }
+    }
+
+    private static void createZip(File file, File zfile) throws Exception {
+
+        XSSFWorkbook wb = null;
+        try {
+            wb = new XSSFWorkbook(file);
+            int num = wb.getNumberOfSheets();
+            if (num == 1) {
+                throw new Exception("没有试卷信息:" + file.getName());
+            }
+            Set<String> ques = new HashSet<String>();
+            for (int i = 1; i < num; i++) {
+                XSSFSheet sheet = wb.getSheetAt(i);
+                int rows = sheet.getLastRowNum();
+                for (int j = 1; j <= rows; j++) {
+                    XSSFRow row = sheet.getRow(j);
+                    ques.add(row.getCell(0).getStringCellValue());
+                }
+            }
+            List<File> files = new ArrayList<File>();
+            for (String s : ques) {
+                File f = new File(sourceQuesDir + s + ".txt");
+                files.add(f);
+            }
+            files.add(file);
+            FileUtil.doZip(files, zfile);
+        } finally {
+            if (wb != null) {
+                wb.close();
+            }
+        }
+    }
+
+    private static void submitZip(File zfile) throws Exception {
+        Map<String, String> params = Maps.newHashMap();
+        params.put("rootOrgId", rootOrgId);
+        Map<String, String> headers = Maps.newHashMap();
+        headers.put("key", key);
+        headers.put("token", token);
+        List<FormFilePart> fileList = Lists.newArrayList();
+        fileList.add(new FormFilePart("dataFile", zfile.getName(), zfile));
+        Response resp = null;
+        try {
+            resp = OKHttpUtil.call(HttpMethod.POST, url, headers, params, fileList);
+            if (resp.code() != 200) {
+                throw new Exception(zfile.getName() + ":body:" + resp.body().string());
+            }
+        } finally {
+            IOUtils.closeQuietly(resp);
+        }
+    }
+}

+ 53 - 0
src/main/java/cn/com/qmth/importpaper/JsonUtil.java

@@ -0,0 +1,53 @@
+package cn.com.qmth.importpaper;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import cn.com.qmth.importpaper.DateUtil.DatePatterns;
+
+/**
+ * 类注释
+ *
+ * @author WANGWEI
+ */
+public class JsonUtil {
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param obj
+	 * @return
+	 */
+	public static String toJson(Object obj) {
+		Gson gson = new GsonBuilder().disableHtmlEscaping().setDateFormat(DatePatterns.ISO)
+				.create();
+		return gson.toJson(obj);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param obj
+	 * @return
+	 */
+	public static String toPrettyJson(Object obj) {
+		Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting()
+				.setDateFormat(DatePatterns.ISO).create();
+		return gson.toJson(obj);
+	}
+
+	/**
+	 * 方法注释
+	 *
+	 * @author WANGWEI
+	 * @param json
+	 * @param c
+	 * @return
+	 */
+	public static <T> T fromJson(String json, Class<T> c) {
+		Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+		return gson.fromJson(json, c);
+	}
+
+}

+ 289 - 0
src/main/java/cn/com/qmth/importpaper/OKHttpUtil.java

@@ -0,0 +1,289 @@
+package cn.com.qmth.importpaper;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import okhttp3.FormBody;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Request.Builder;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+/**
+ * OKHttp
+ *
+ * @author WANGWEI
+ * @date 2018年9月6日
+ * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
+ */
+public class OKHttpUtil {
+
+
+	public static final class MediaTypes {
+
+		public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+	}
+
+	/**
+	 * 请求体构建器
+	 *
+	 * @author WANGWEI
+	 * @date 2019年4月10日
+	 * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
+	 */
+	public static interface RequestBodyBuilder {
+		RequestBody build();
+	}
+
+	/**
+	 * json请求体构建器
+	 *
+	 * @author WANGWEI
+	 * @date 2019年4月10日
+	 * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
+	 */
+	public static final class JsonBodyBuilder implements RequestBodyBuilder {
+
+		private String json;
+
+		public JsonBodyBuilder(String json) {
+			super();
+			this.json = json;
+		}
+
+		@Override
+		public RequestBody build() {
+			return RequestBody.create(MediaTypes.JSON, json);
+		}
+
+		@Override
+		public String toString() {
+			return json;
+		}
+	}
+
+	private static OkHttpClient okHttpClient;
+
+	static {
+		okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)
+				.readTimeout(300, TimeUnit.SECONDS).build();
+	}
+
+	public static OkHttpClient getOkHttpClient() {
+		return okHttpClient;
+	}
+
+	/**
+	 * 发送请求 (带json请求体)
+	 *
+	 * @author WANGWEI
+	 * @param httpMethod
+	 * @param url
+	 * @param headers
+	 * @param jsonBody
+	 * @return
+	 */
+	public static Response call(HttpMethod httpMethod, String url, Map<String, String> headers,
+			String jsonBody) {
+		return call(httpMethod, url, headers, new JsonBodyBuilder(jsonBody));
+	}
+
+	/**
+	 * 发送请求 (带请求体)
+	 *
+	 * @author WANGWEI
+	 * @param httpMethod
+	 * @param url
+	 * @param headers
+	 * @param requestBodyBuilder
+	 * @return
+	 */
+	public static Response call(HttpMethod httpMethod, String url, Map<String, String> headers,
+			RequestBodyBuilder requestBodyBuilder) {
+
+
+		Builder builder = null;
+		if (httpMethod.equals(HttpMethod.POST)) {
+			builder = new Request.Builder().url(url).post(requestBodyBuilder.build());
+		} else if (httpMethod.equals(HttpMethod.PUT)) {
+			builder = new Request.Builder().url(url).put(requestBodyBuilder.build());
+		} else if (httpMethod.equals(HttpMethod.DELETE)) {
+			builder = new Request.Builder().url(url).delete(requestBodyBuilder.build());
+		}
+
+		if (null != headers && 0 != headers.size()) {
+			for (Entry<String, String> entry : headers.entrySet()) {
+				builder.addHeader(entry.getKey(), entry.getValue());
+			}
+		}
+
+		Request request = builder.build();
+
+		Response response = null;
+		try {
+			response = okHttpClient.newCall(request).execute();
+			return response;
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * 发送请求
+	 *
+	 * @author WANGWEI
+	 * @param httpMethod
+	 * @param url
+	 * @return
+	 */
+	public static Response call(HttpMethod httpMethod, String url) {
+		return call(httpMethod, url, null);
+	}
+
+	/**
+	 * 发送请求
+	 *
+	 * @author WANGWEI
+	 * @param httpMethod
+	 * @param url
+	 * @param headers
+	 * @return
+	 */
+	public static Response call(HttpMethod httpMethod, String url, Map<String, String> headers) {
+
+
+		Builder builder = null;
+		if (httpMethod.equals(HttpMethod.GET)) {
+			builder = new Request.Builder().url(url);
+		} else if (httpMethod.equals(HttpMethod.POST)) {
+			builder = new Request.Builder().url(url).post(new FormBody.Builder().build());
+		} else if (httpMethod.equals(HttpMethod.PUT)) {
+			builder = new Request.Builder().url(url).put(new FormBody.Builder().build());
+		} else if (httpMethod.equals(HttpMethod.DELETE)) {
+			builder = new Request.Builder().url(url).delete(new FormBody.Builder().build());
+		}
+
+		if (null != headers && 0 != headers.size()) {
+			for (Entry<String, String> entry : headers.entrySet()) {
+				builder.addHeader(entry.getKey(), entry.getValue());
+			}
+		}
+
+		Request request = builder.build();
+
+		Response response = null;
+		try {
+			response = okHttpClient.newCall(request).execute();
+			return response;
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * 发送请求 (表单)
+	 *
+	 * @author WANGWEI
+	 * @param httpMethod
+	 * @param url
+	 * @param headers
+	 * @param params
+	 * @return
+	 */
+	public static Response call(HttpMethod httpMethod, String url, Map<String, String> headers,
+			Map<String, String> params) {
+
+		okhttp3.FormBody.Builder formBody = new FormBody.Builder();
+
+		if (null != params && 0 != params.size()) {
+			for (Entry<String, String> entry : params.entrySet()) {
+				formBody.add(entry.getKey(), entry.getValue());
+			}
+		}
+
+		Builder builder = null;
+		if (httpMethod.equals(HttpMethod.POST)) {
+			builder = new Request.Builder().url(url).post(formBody.build());
+		} else if (httpMethod.equals(HttpMethod.PUT)) {
+			builder = new Request.Builder().url(url).put(formBody.build());
+		} else if (httpMethod.equals(HttpMethod.DELETE)) {
+			builder = new Request.Builder().url(url).delete(formBody.build());
+		}
+
+		if (null != headers && 0 != headers.size()) {
+			for (Entry<String, String> entry : headers.entrySet()) {
+				builder.addHeader(entry.getKey(), entry.getValue());
+			}
+		}
+
+		Request request = builder.build();
+
+		Response response = null;
+		try {
+			response = okHttpClient.newCall(request).execute();
+			return response;
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * 发送请求 (包含文件表单)
+	 *
+	 * @author WANGWEI
+	 * @param httpMethod
+	 * @param url
+	 * @param headers
+	 * @param params
+	 * @param formFilePartList
+	 * @return
+	 */
+	public static Response call(HttpMethod httpMethod, String url, Map<String, String> headers,
+			Map<String, String> params, List<FormFilePart> formFilePartList) {
+
+
+		okhttp3.MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder()
+				.setType(MultipartBody.ALTERNATIVE);
+
+		if (null != params) {
+			for (Entry<String, String> entry : params.entrySet()) {
+				multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
+			}
+		}
+
+		if (CollectionUtils.isNotEmpty(formFilePartList)) {
+			MediaType type = MediaType.parse("application/octet-stream");
+			for (FormFilePart part : formFilePartList) {
+				RequestBody fileBody = RequestBody.create(type, part.getFile());
+				multipartBodyBuilder.addFormDataPart(part.getParamName(), part.getFilename(),
+						fileBody);
+			}
+		}
+
+		Builder builder = new Request.Builder().url(url).post(multipartBodyBuilder.build());
+		if (null != headers && 0 != headers.size()) {
+			for (Entry<String, String> entry : headers.entrySet()) {
+				builder.addHeader(entry.getKey(), entry.getValue());
+			}
+		}
+
+		Request request = builder.build();
+
+		Response response = null;
+		try {
+			response = okHttpClient.newCall(request).execute();
+			return response;
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+}

+ 79 - 0
src/main/java/cn/com/qmth/importpaper/ReWriteExcel.java

@@ -0,0 +1,79 @@
+package cn.com.qmth.importpaper;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.Date;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+public class ReWriteExcel {
+	private static Logger logger = LogManager.getLogger(ReWriteExcel.class);
+	private static String sourceDir = "C:\\Users\\chenken\\Desktop\\temp\\excelDir";
+	private static String targetDir = "C:\\Users\\chenken\\Desktop\\temp\\targetDir\\";
+	private static String suff="(2019)";
+
+	public static void main(String[] args) {
+		logger.debug("**********************处理开始");
+		Date start=new Date();
+		int errnum=0;
+		int num=0;
+		StringBuilder sb=new StringBuilder();
+		String fname = null;
+		File dir = new File(sourceDir);
+		for (File f : dir.listFiles()) {
+			fname = f.getName();
+			if (!f.isDirectory() && fname.endsWith(".xlsx")) {
+				num++;
+				Date n=new Date();
+				try {
+					write(f);
+					Date et=new Date();
+					logger.debug("处理成功("+num+"):" + fname+" 耗时:"+(et.getTime()-n.getTime()));
+				} catch (Exception e) {
+					errnum++;
+					sb.append(fname).append(",");
+					Date et=new Date();
+					logger.error("处理失败("+num+"):" + fname+" 耗时:"+(et.getTime()-n.getTime())+" "+e.getMessage(), e);
+				}
+			}
+		}
+		
+		Date end=new Date();
+		logger.debug("**********************处理结束  耗时:"+(end.getTime()-start.getTime()));
+		
+		logger.debug("**********************处理出错数:"+errnum);
+		logger.debug("**********************处理出错课程:"+sb.toString());
+	}
+
+
+	private static void write(File file) throws Exception {
+
+		XSSFWorkbook wb = null;
+		OutputStream os=null;
+		try {
+			wb = new XSSFWorkbook(file);
+			XSSFSheet sheet = wb.getSheetAt(0);
+			int rows = sheet.getLastRowNum();
+			for (int j = 1; j <= rows; j++) {
+				XSSFRow row = sheet.getRow(j);
+				String s=row.getCell(1).getStringCellValue();
+				row.getCell(1).setCellValue(s+suff);
+			}
+			os = new FileOutputStream(targetDir+file.getName());
+			wb.write(os);
+		} finally {
+			if (wb != null) {
+				wb.close();
+			}
+			if (os != null) {
+				os.close();
+			}
+		}
+	}
+
+}

+ 285 - 0
src/main/java/cn/com/qmth/importpaper/Temp.java

@@ -0,0 +1,285 @@
+package cn.com.qmth.importpaper;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+
+import cn.com.qmth.S;
+import cn.com.qmth.multithread.ComputeConsumer;
+import cn.com.qmth.multithread.ComputeProducer;
+import cn.com.qmth.multithread.Consumer;
+
+public class Temp {
+
+//    public static String[] arr = { "a", "b", "c", "d", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
+//            "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
+    
+    public static String[] arr = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
+
+    public static void main(String[] args) {
+//        cre();
+    }
+    public static byte[] decodeValue(ByteBuffer bytes) {
+        int len = bytes.limit() - bytes.position();
+        byte[] bytes1 = new byte[len];
+        bytes.get(bytes1);
+        return bytes1;
+    }
+    public static boolean isUtf8(byte[] line) {
+        try {
+            byte[] tem=new String(line,"utf-8").getBytes("utf-8");
+            return Arrays.equals(tem, line);
+        } catch (UnsupportedEncodingException e) {
+            return false;
+        }
+    }
+    public static void cre() {
+        Set<String> set4 = word5();
+        File re = new File("d:\\word.txt");
+        if(re.exists()) {
+            re.delete();
+        }
+        try {
+            re.createNewFile();
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        try {
+            FileUtils.writeLines(re, set4, "\n", true);
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+    public static void dis() {
+        try {
+            File re = new File("d:\\ret.txt");
+            File unre = new File("d:\\unret.txt");
+            if (re.exists()) {
+                re.delete();
+            }
+            if (unre.exists()) {
+                unre.delete();
+            }
+            re.createNewFile();
+            unre.createNewFile();
+            ComputeProducer p = new ComputeProducer();
+            p.startDispose(ComputeConsumer.class, 20, null);
+            for (Consumer c : p.consumers) {
+                c.disposeOnEnd(re, unre);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (InstantiationException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按1位组合,可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:57:31
+     */
+    public static Set<String> word1() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            set.add(l1);
+        }
+        return set;
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按2位组合,可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:57:31
+     */
+    public static Set<String> word2() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                String l2 = arr[j];
+                String result = l1 + l2;
+                set.add(result);
+            }
+        }
+        return set;
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按3位组合,可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:57:31
+     */
+    public static Set<String> word3() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                if (j != i) {
+                    String l2 = arr[j];
+                    for (int k = 0; k < arr.length; k++) {
+                        String l3 = arr[k];
+                        String result = l1 + l2 + l3;
+                        set.add(result);
+                    }
+                }
+            }
+        }
+        return set;
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按4位组合,可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:47:39
+     */
+    public static Set<String> word4() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                String l2 = arr[j];
+                for (int k = 0; k < arr.length; k++) {
+                    String l3 = arr[k];
+                    for (int m = 0; m < arr.length; m++) {
+                        String l4 = arr[m];
+                        String result = l1 + l2 + l3 + l4;
+                        set.add(result);
+                    }
+                }
+            }
+        }
+        return set;
+    }
+    /**
+     * @Description:26个纯字母不分大小写,按4位组合,可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:47:39
+     */
+    public static Set<String> word5() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                String l2 = arr[j];
+                for (int k = 0; k < arr.length; k++) {
+                    String l3 = arr[k];
+                    for (int m = 0; m < arr.length; m++) {
+                        String l4 = arr[m];
+                        for (int n = 0; n < arr.length; n++) {
+                            String l5 = arr[n];
+                            String result = l1 + l2 + l3 + l4+l5;
+                            set.add(result);
+                        }
+                    }
+                }
+            }
+        }
+        return set;
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按4位组合,不可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:57:31
+     */
+    public static Set<String> question2() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                if (j != i) {
+                    String l2 = arr[j];
+                    for (int k = 0; k < arr.length; k++) {
+                        if (k != i && k != j) {
+                            String l3 = arr[k];
+                            for (int m = 0; m < arr.length; m++) {
+                                if (m != i && m != j && m != k) {
+                                    String l4 = arr[m];
+                                    String result = l1 + l2 + l3 + l4;
+                                    set.add(result);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return set;
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按5位组合,可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:47:39
+     */
+    public static Set<String> question3() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                String l2 = arr[j];
+                for (int k = 0; k < arr.length; k++) {
+                    String l3 = arr[k];
+                    for (int m = 0; m < arr.length; m++) {
+                        String l4 = arr[m];
+                        for (int n = 0; n < arr.length; n++) {
+                            String l5 = arr[n];
+                            String result = l1 + l2 + l3 + l4 + l5;
+                            set.add(result);
+                        }
+                    }
+                }
+            }
+        }
+        return set;
+    }
+
+    /**
+     * @Description:26个纯字母不分大小写,按5位组合,不可重复。求出各种组合结果
+     * @return
+     * @date: 2017年11月18日 下午1:57:31
+     */
+    public static Set<String> question4() {
+        Set<String> set = new HashSet<String>();
+        for (int i = 0; i < arr.length; i++) {
+            String l1 = arr[i];
+            for (int j = 0; j < arr.length; j++) {
+                if (j != i) {
+                    String l2 = arr[j];
+                    for (int k = 0; k < arr.length; k++) {
+                        if (k != i && k != j) {
+                            String l3 = arr[k];
+                            for (int m = 0; m < arr.length; m++) {
+                                if (m != i && m != j && m != k) {
+                                    String l4 = arr[m];
+                                    for (int n = 0; n < arr.length; n++) {
+                                        if (m != i && m != j && m != k) {
+                                            String l5 = arr[n];
+                                            String result = l1 + l2 + l3 + l4 + l5;
+                                            set.add(result);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return set;
+    }
+}

+ 172 - 0
src/main/java/cn/com/qmth/importpaper/Temp2.java

@@ -0,0 +1,172 @@
+package cn.com.qmth.importpaper;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.ParseException;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+
+public class Temp2 {
+
+    private final static String url1 = "https://checkapi.aliyun.com/check/checkdomain?";
+
+    private final static Pattern p = Pattern.compile("^[^a-z]*([a-z]*)(.*)$");
+
+    private final static String param = "&command=renew&token=Y55524d856a54264296cc7773dbb65292&ua=&currency=&site=&bid=&_csrf_token=&callback=jsonp_1589269263490_77956";
+
+    private final static int batchSize = 500000;
+
+    private final static int start = 68427;
+
+    private static int errTime = 0;
+    
+    private static int maxErrTime = 10;
+    
+    private static CloseableHttpClient client ;
+    private static RequestConfig defaultRequestConfig = RequestConfig.custom()
+            .setSocketTimeout(5000)
+            .setConnectTimeout(5000)
+            .setConnectionRequestTimeout(5000)
+            .build();
+    public static void main(String[] args) {
+        client = HttpClients.custom()
+                .setDefaultRequestConfig(defaultRequestConfig)
+                .build();
+        List<String> reList = new ArrayList<String>();
+        List<String> unreList = new ArrayList<String>();
+        int index = 0;
+        File re = new File("d:\\ret.txt");
+        File unre = new File("d:\\unret.txt");
+        try {
+            if (re.exists()) {
+                re.delete();
+            }
+            if (unre.exists()) {
+                unre.delete();
+            }
+            re.createNewFile();
+            unre.createNewFile();
+            
+            Map<String, String> map = parse();
+            for (String k : map.keySet()) {
+                String dmain = k + ".com";
+                char c = getRet(dmain);
+                if (c == '1') {
+                    reList.add(k);
+                } else {
+                    unreList.add(k);
+                }
+                index++;
+                System.out.println("**************************index:" + index);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            System.out.println("**************************count:" + reList.size());
+            System.out.println("**************************un count:" + unreList.size());
+            System.out.println("**************************end index:" + (index + start));
+            try {
+                FileUtils.writeLines(re, reList);
+                FileUtils.writeLines(unre, unreList);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private static char getRet(String dmain) {
+        try {
+            
+            String ret = getData(client, url1 + "domain=" + dmain + param);
+            char c = ret.charAt(ret.indexOf("\"avail\":") + 8);
+            errTime=0;
+            return c;
+        } catch (Exception e) {
+            errTime++;
+            if (errTime <= maxErrTime) {
+                client = HttpClients.custom()
+                        .setDefaultRequestConfig(defaultRequestConfig)
+                        .build();
+                return getRet(dmain);
+            } else {
+                throw new RuntimeException("error:" + e.getMessage());
+            }
+        }
+
+    }
+
+    public static Map<String, String> parse() throws IOException {
+        Map<String, String> map = new HashMap<String, String>();
+        List<String> list = readFile();
+        for (String s : list) {
+//            Matcher m = p.matcher(s);
+//            if (m.find()) {
+//                String k = m.group(1);
+//                String v = m.group(2);
+//                if (!"".equals(k)) {
+//                    map.put(k, v);
+//                }
+//            }
+            if (!"".equals(s)) {
+              map.put(s, s);
+            }
+        }
+        return map;
+    }
+
+    public static List<String> readFile() throws IOException {
+        int index = 0;
+        List<String> list = new ArrayList<String>();
+        FileInputStream fis = new FileInputStream("d:\\word.txt");
+        InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+        BufferedReader br = new BufferedReader(isr);
+        String line = "";
+        while ((line = br.readLine()) != null) {
+            if (start <= index && index < start + batchSize) {
+                list.add(line.toLowerCase());
+            }
+            index++;
+        }
+        br.close();
+        isr.close();
+        fis.close();
+        return list;
+    }
+
+    public static String getData(CloseableHttpClient client, String url) {
+        HttpGet get = new HttpGet(url);
+        try {
+            CloseableHttpResponse response = client.execute(get);
+            int statusCode = response.getStatusLine().getStatusCode();
+            if (statusCode == 200) {
+                HttpEntity entity = response.getEntity();
+                String data = EntityUtils.toString(entity, "UTF-8");
+                return data;
+            }
+        } catch (ClientProtocolException e) {
+            e.printStackTrace();
+        } catch (ParseException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

+ 104 - 0
src/main/java/cn/com/qmth/multithread/Basket.java

@@ -0,0 +1,104 @@
+package cn.com.qmth.multithread;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+
+import cn.com.qmth.importpaper.FileUtil;
+
+
+
+public  class  Basket {
+    private static Logger logger = Logger.getLogger(Basket.class);
+	/**
+	 * 数据阻塞队列
+	 */
+	private BlockingQueue<Object> queue;
+	
+	/**
+	 * 多线程计数器,子线程都结束后主线程才继续执行
+	 */
+	private CountDownLatch endGate;
+	
+	/**
+	 * 消费者数量
+	 */
+	private int consumerCount;
+	
+	
+	/**
+	 * 判断线程执行是否有出错,生产者、消费者出错都需要修改此值为true
+	 */
+	private boolean isExcuteError = false;
+	
+	
+	public Basket(int consumerCount) {
+		this.consumerCount=consumerCount;
+		queue = new ArrayBlockingQueue<Object>(consumerCount*2);
+		endGate = new CountDownLatch(consumerCount);
+	}
+
+	/**
+	 * 生产数据,不采用put方法防止消费线程全部异常后生产线程阻塞
+	 * @param value
+	 * @throws InterruptedException
+	 */
+	protected void offer(final Object value) throws InterruptedException {
+		if(isExcuteError) {
+			logger.error("**********************offer isExcuteError threadId:"+Thread.currentThread().getId());
+			throw new StatusException("1000001","线程异常");
+		}else {
+			boolean ret=queue.offer(value, 1, TimeUnit.MINUTES);
+			if(!ret) {
+				logger.info("**********************offer time out threadId:"+Thread.currentThread().getId()+value);
+				this.offer(value);
+			}
+		}
+	}
+	/**
+	 * 消费数据,不采用take方法防止生产线程全部异常后消费线程阻塞
+	 * @return
+	 * @throws InterruptedException
+	 */
+	protected Object consume() throws InterruptedException {
+		if(isExcuteError) {
+			logger.error("**********************poll isExcuteError  threadId:"+Thread.currentThread().getId());
+			return new EndObject();
+		}else {
+			Object ob=queue.poll(1, TimeUnit.MINUTES);
+			if(ob==null) {
+				logger.info("**********************poll time out  threadId:"+Thread.currentThread().getId());
+				return this.consume();
+			}else {
+				return ob;
+			}
+		}
+	}
+	
+	protected void await() throws InterruptedException {
+		endGate.await();
+	}
+	protected void countDown() {
+		endGate.countDown();
+	}
+
+	protected boolean isExcuteError() {
+		return isExcuteError;
+	}
+
+	protected void setExcuteError(boolean isExcuteError) {
+		this.isExcuteError = isExcuteError;
+	}
+
+	protected int getConsumerCount() {
+		return consumerCount;
+	}
+
+	protected void setConsumerCount(int consumerCount) {
+		this.consumerCount = consumerCount;
+	}
+
+}

+ 78 - 0
src/main/java/cn/com/qmth/multithread/ComputeConsumer.java

@@ -0,0 +1,78 @@
+package cn.com.qmth.multithread;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.apache.log4j.Logger;
+
+public class ComputeConsumer extends Consumer<Kv> {
+
+    private static final Logger logger = Logger.getLogger(ComputeConsumer.class);
+
+    private CloseableHttpClient client = HttpClients.createDefault();
+
+    private final static String url1 = "https://checkapi.aliyun.com/check/checkdomain?";
+
+    private final static String param = "&command=&token=Y9506071268d5ca43e4e356f0fb6b6023&ua=&currency=&site=&bid=&_csrf_token=&callback=jsonp_1575251283490_63951";
+
+    private List<Kv> cret = new ArrayList<Kv>();
+
+    private List<Kv> cunret = new ArrayList<Kv>();
+
+    @Override
+    public void consume(Kv et) {
+        logger.info("***************************计算开始");
+        String dmain = et.getKey() + ".com";
+        String ret = getData(url1 + "domain=" + dmain + param);
+        char c = ret.charAt(ret.indexOf("\"avail\":") + 8);
+        if (c == '1') {
+            cret.add(et);
+        } else {
+            cunret.add(et);
+        }
+        logger.info("***************************计算结束");
+    }
+
+    private String getData(String url) {
+        HttpGet get = new HttpGet(url);
+        try {
+            CloseableHttpResponse response = client.execute(get);
+            int statusCode = response.getStatusLine().getStatusCode();
+            HttpEntity entity = response.getEntity();
+            String data = EntityUtils.toString(entity, "UTF-8");
+            if (statusCode == 200) {
+                return data;
+            }else {
+                logger.error("***************************计算结束出错:-->"+data+"-->"+url);
+                return "";
+            }
+        } catch (Exception e) {
+            logger.error("***************************计算结束出错:"+e.getMessage());
+        }
+        return "";
+    }
+
+    @Override
+    public void disposeOnEnd(File re, File unre) {
+        try {
+            for (Kv o : cret) {
+                FileUtils.write(re, o.getKey() + " : " + o.getValue() + "\n", "utf-8", true);
+            }
+            for (Kv o : cunret) {
+                FileUtils.write(unre, o.getKey() + " : " + o.getValue() + "\n", "utf-8", true);
+            }
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+}

+ 72 - 0
src/main/java/cn/com/qmth/multithread/ComputeProducer.java

@@ -0,0 +1,72 @@
+package cn.com.qmth.multithread;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+public class ComputeProducer extends Producer {
+    
+    private static final Logger logger = Logger.getLogger(ComputeProducer.class);
+    
+    private final static Pattern p = Pattern.compile("^[^a-z]*([a-z]*)(.*)$");
+
+    @Override
+    protected void produce(Map<String, Object> param) throws Exception {
+        logger.info("***************************任务生产开始");
+        List<Kv> list = parse();
+        if (list != null && list.size() > 0) {
+            for (Kv et : list) {
+                // 生产数据
+                offer(et);
+            }
+        }
+        logger.info("***************************任务生产结束");
+    }
+
+    private List<Kv> parse() throws IOException {
+        List<Kv> ret = new ArrayList<Kv>();
+        List<String> list = readFile();
+        for (String s : list) {
+            Matcher m = p.matcher(s);
+            if (m.find()) {
+                String k = m.group(1);
+                String v = m.group(2);
+                if (k!=null&&v!=null) {
+                    Kv o = new Kv(k, v);
+                    ret.add(o);
+                }
+            }
+        }
+        return ret;
+    }
+
+    private List<String> readFile() throws IOException {
+        int start=14000;
+        int c=4000;
+        int index=1;
+        List<String> list = new ArrayList<String>();
+        FileInputStream fis = new FileInputStream("d:\\cc.txt");
+        InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+        BufferedReader br = new BufferedReader(isr);
+        String line = "";
+        while ((line = br.readLine()) != null) {
+            if(start<=index&&index<start+c) {
+                list.add(line.toLowerCase());
+            }
+            index++;
+        }
+        
+        br.close();
+        isr.close();
+        fis.close();
+        return list;
+    }
+}

+ 62 - 0
src/main/java/cn/com/qmth/multithread/Consumer.java

@@ -0,0 +1,62 @@
+package cn.com.qmth.multithread;
+
+import java.io.File;
+
+import org.apache.log4j.Logger;
+import org.apache.logging.log4j.ThreadContext;
+
+public abstract class Consumer<T>  extends Thread{
+	private static final Logger logger = Logger.getLogger(Consumer.class);
+	private Basket basket;
+	
+	private String traceId;
+	
+	public Consumer() {
+	}
+	@Override
+	public void run() {
+		ThreadContext.put("TRACE_ID", traceId);
+		logger.info("*******************Consumer:"+Thread.currentThread().getId()+" start");
+		try {
+			while (true) {
+				//先判断是否有异常结束
+				if(basket.isExcuteError()) {
+					break;
+				}
+				//取消费数据
+				Object o= basket.consume();
+				//判断消费数据是否是结束
+				if(o instanceof EndObject) {
+					break;
+				}
+				@SuppressWarnings("unchecked")
+				T t=(T)o;
+				logger.info("*******************Consumer:"+Thread.currentThread().getId()+" consume");
+				//消费数据实现
+				consume(t);
+			}
+		} catch (Exception e) {
+			basket.setExcuteError(true);
+			logger.info("消费线程处理出错",e);
+		}finally {
+			basket.countDown();
+			logger.info("*******************Consumer:"+Thread.currentThread().getId()+" stop");
+			ThreadContext.clearAll();
+		}
+	}
+	public abstract void consume(T t);
+	public Basket getBasket() {
+		return basket;
+	}
+	public void setBasket(Basket basket) {
+		this.basket = basket;
+	}
+	public String getTraceId() {
+		return traceId;
+	}
+	public void setTraceId(String traceId) {
+		this.traceId = traceId;
+	}
+	public abstract void disposeOnEnd(File re,File unre);
+	
+}

+ 10 - 0
src/main/java/cn/com/qmth/multithread/EndObject.java

@@ -0,0 +1,10 @@
+package cn.com.qmth.multithread;
+
+/**
+ * 消费结束标识对象
+ * @author xiatian
+ *
+ */
+public class EndObject {
+
+}

+ 30 - 0
src/main/java/cn/com/qmth/multithread/Kv.java

@@ -0,0 +1,30 @@
+package cn.com.qmth.multithread;
+
+
+public class Kv {
+    private String key;
+    private String value;
+    
+    public Kv(String key, String value) {
+        super();
+        this.key = key;
+        this.value = value;
+    }
+
+    public String getKey() {
+        return key;
+    }
+    
+    public void setKey(String key) {
+        this.key = key;
+    }
+    
+    public String getValue() {
+        return value;
+    }
+    
+    public void setValue(String value) {
+        this.value = value;
+    }
+    
+}

+ 138 - 0
src/main/java/cn/com/qmth/multithread/Producer.java

@@ -0,0 +1,138 @@
+package cn.com.qmth.multithread;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.logging.log4j.ThreadContext;
+
+public abstract class Producer {
+	private static final Logger logger = Logger.getLogger(Producer.class);
+	private Basket basket;
+	
+	/**
+	 * 业务参数
+	 */
+	private Map<String, Object> param;
+	
+	/**
+	 * 消费线程class
+	 */
+	private Class<? extends Consumer<?>> consumer;
+	
+	public List<Consumer> consumers=new ArrayList<Consumer>();
+	/**
+	 * 	处理开始方法
+	 * @param consumer 消费线程class
+	 * @param consumerCount 消费线程数
+	 * @param param 生产者业务参数
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 */
+	public void startDispose(Class<? extends Consumer<?>> consumer, int consumerCount,Map<String, Object> param)
+			throws InstantiationException, IllegalAccessException {
+		Basket basket = new Basket(consumerCount);
+		this.basket = basket;
+		this.consumer = consumer;
+		this.param=param;
+		//启动消费者
+		startConsumer();
+		//开始处理
+		dispose();
+	}
+
+	private void dispose() {
+		try {
+			logger.info("*******************Producer:开始处理");
+			// 生产数据
+			produce(param);
+			logger.info("*******************Producer:生产结束");
+			// 发送生产结束信息
+			endConsumer();
+			logger.info("*******************Producer:成功发送生产结束信息");
+			// 等待子线程结束
+			logger.info("*******************Producer:等待消费线程结束");
+			await();
+			logger.info("*******************Producer:消费线程已结束");
+			// 判断子线程是否正常结束
+			if (basket.isExcuteError()) {
+				throw new StatusException("1000001", "处理失败,线程异常");
+			}
+			logger.info("*******************Producer:结束处理");
+		} catch (StatusException e) {
+			// 获取异常时发送异常结束信息
+			endConsumerAsError();
+			throw e;
+		} catch (Exception e) {
+			// 获取异常时发送异常结束信息
+			endConsumerAsError();
+			throw new StatusException("1000002", "处理失败", e);
+		}
+	}
+
+	/**
+	 * 启动消费者
+	 * 
+	 * @param consumer
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 */
+	private void startConsumer() throws InstantiationException, IllegalAccessException {
+		int count = basket.getConsumerCount();
+		for (int i = 0; i < count; i++) {
+			Consumer<?> co = (Consumer<?>) consumer.newInstance();
+			co.setBasket(basket);
+			co.setTraceId(ThreadContext.get("TRACE_ID"));
+			consumers.add(co);
+			co.start();
+		}
+
+	}
+
+	/**
+	 * 出异常后修改标识
+	 * 
+	 */
+	private void endConsumerAsError() {
+		basket.setExcuteError(true);
+	}
+
+	/**
+	 * 正常结束消费者
+	 * 
+	 * @throws InterruptedException
+	 */
+	private void endConsumer() throws InterruptedException {
+		int count = basket.getConsumerCount();
+		EndObject eo = new EndObject();
+		for (int i = 0; i < count; i++) {
+			basket.offer(eo);
+		}
+
+	}
+
+	/**
+	 * 生产数据
+	 * 
+	 * @param ob
+	 * @throws InterruptedException
+	 */
+	protected void offer(Object ob) throws InterruptedException {
+		synchronized (basket) {
+			basket.offer(ob);
+		}
+	}
+
+	/**
+	 * 等待所有消费者结束
+	 * 
+	 * @throws InterruptedException
+	 */
+	private void await() throws InterruptedException {
+		basket.await();
+	}
+
+	protected abstract void produce(Map<String, Object> param) throws Exception;
+
+}

+ 80 - 0
src/main/java/cn/com/qmth/multithread/StatusException.java

@@ -0,0 +1,80 @@
+package cn.com.qmth.multithread;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import cn.com.qmth.importpaper.JsonUtil;
+
+/**
+ * 状态异常类<br>
+ *
+ * @author WANG
+ */
+public class StatusException extends RuntimeException {
+	private static final long serialVersionUID = 5003047488500388819L;
+
+	/**
+	 * 追踪ID
+	 */
+	private String traceId;
+
+	/**
+	 * 状态码
+	 */
+	private String code;
+
+	/**
+	 * 状态描述
+	 */
+	private String desc;
+
+	/**
+	 * 构造函数
+	 */
+	public StatusException(String code, String desc) {
+		super("[code: " + code + "; desc: " + desc + "]");
+		this.code = code;
+		this.desc = desc;
+	}
+
+	/**
+	 * 构造函数
+	 */
+	public StatusException(String code, String desc, Throwable cause) {
+		super("[code: " + code + "; desc: " + desc + "]", cause);
+		this.code = code;
+		this.desc = desc;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public String getDesc() {
+		return desc;
+	}
+
+	public String getTraceId() {
+		return traceId;
+	}
+
+	public void setTraceId(String traceId) {
+		this.traceId = traceId;
+	}
+
+	/**
+	 * @return
+	 */
+	public String toJson() {
+		Map<String, Object> map = new HashMap<String, Object>();
+		map.put("code", code);
+		map.put("desc", desc);
+		return JsonUtil.toJson(map);
+	}
+
+	@Override
+	public String toString() {
+		return toJson();
+	}
+
+}

+ 124 - 0
src/main/resources/application.properties

@@ -0,0 +1,124 @@
+management.endpoints.web.exposure.include=*
+
+spring.jpa.hibernate.ddl-auto=update
+
+spring.main.allow-bean-definition-overriding=true
+
+spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
+spring.jackson.time-zone=GMT+8
+
+eureka.instance.lease-renewal-interval-in-seconds=3
+eureka.instance.lease-expiration-duration-in-seconds=6
+eureka.instance.prefer-ip-address=true
+eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
+eureka.client.healthcheck.enabled=true
+eureka.client.registry-fetch-interval-seconds=3
+eureka.client.instance-info-replication-interval-seconds=5
+eureka.client.initial-instance-info-replication-interval-seconds=5
+
+eureka.client.serviceUrl.defaultZone=http://192.168.1.210:1111/eureka/
+
+#datasource
+dsurl.host=qmth-db4.mysql.rds.aliyuncs.com
+dsurl.port=3306
+dsurl.database=exam_cloud_dev
+spring.datasource.username=exam_cloud_dev
+spring.datasource.password=Examcloud123
+
+spring.datasource.url=jdbc:mysql://${dsurl.host}:${dsurl.port}/${dsurl.database}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2b8
+spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
+spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
+
+#druid
+spring.datasource.druid.initial-size=5
+spring.datasource.druid.min-idle=5
+spring.datasource.druid.max-active=10
+spring.datasource.druid.max-wait=500
+spring.datasource.druid.validation-query=SELECT 1
+spring.datasource.druid.validation-query-timeout=2000
+spring.datasource.druid.test-on-borrow=false
+spring.datasource.druid.test-on-return=false
+spring.datasource.druid.test-while-idle=true
+spring.datasource.druid.time-between-eviction-runs-millis=10000
+spring.datasource.druid.min-evictable-idle-time-millis=120000
+spring.datasource.druid.filters=config,wall,stat
+spring.datasource.druid.connectionProperties=druid.stat.slowSqlMillis=200;druid.stat.logSlowSql=true;config.decrypt=false
+spring.datasource.druid.web-stat-filter.enabled=true
+spring.datasource.druid.web-stat-filter.url-pattern=/*
+spring.datasource.druid.web-stat-filter.exclusions=/druid/*,*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico
+spring.datasource.druid.web-stat-filter.session-stat-enable=true
+spring.datasource.druid.web-stat-filter.session-stat-max-count=10
+spring.datasource.druid.stat-view-servlet.enabled=true
+spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
+spring.datasource.druid.stat-view-servlet.reset-enable=true
+#spring.datasource.druid.stat-view-servlet.login-username=admin
+#spring.datasource.druid.stat-view-servlet.login-password=admin
+
+spring.redis.host=qmth-redis3.redis.rds.aliyuncs.com
+spring.redis.port=6379
+spring.redis.password=jkhm45-UO8rFc-q2Eb90
+spring.redis.database=1
+
+#log
+examcloud.web.log.normalResponseLogEnable=true
+examcloud.web.log.responseLogJsonMaxSize=1000
+#examcloud.inet.preferredNetworks=^192\.168
+
+#upyun 1
+$upyun.site.1.bucketName=exam-cloud-test
+$upyun.site.1.userName=examcloudtest
+$upyun.site.1.domain=https://ecs-test-static-upyun.qmth.com.cn
+$upyun.site.1.domain.backup=https://ecs-test-static-upyun.qmth.com.cn
+$$.$upyun.site.1.password=e5629881b17cabf9d90ef9299489a588f13c7d76c583c43a24eac5a3c58fd33b2adbd9477b88e9db81c8c89bc20a802c
+
+$aliyun.site.1.bucket=examcloud-test
+$aliyun.site.1.ossEndpoint=https://oss-cn-shenzhen.aliyuncs.com
+$aliyun.site.1.accessKeyId=LTAI4FboXLCJzrjVo5dUoXaU
+$aliyun.site.1.accessKeySecret=O0my6eSAl1Ic62WvxEf3WlMXox1LNX
+$aliyun.site.1.domain=https://ecs-test-static.qmth.com.cn
+
+$aliyun.site.2.bucket=examcloud-test
+$aliyun.site.2.ossEndpoint=https://oss-cn-shenzhen.aliyuncs.com
+$aliyun.site.2.accessKeyId=LTAI4FboXLCJzrjVo5dUoXaU
+$aliyun.site.2.accessKeySecret=O0my6eSAl1Ic62WvxEf3WlMXox1LNX
+$aliyun.site.2.domain=https://ecs-test-static.qmth.com.cn
+
+$upyun.site.num=1
+$aliyun.site.num=2
+
+#facepp
+$$.$facepp.apiKey=eaa307ecbaf419538af50e72696814fb4f9c996af95a274af700a6c5e5f7dcf3bfa78d4dbf5eff682b2682df70531c3f
+$$.$facepp.apiSecret=1a66778cd89df65f5d9edcbdd31b8b9147e7ceff43cec6acf27389e9661429752a6cfc20895bdc1c059e9181a99b9b3c
+$$.$facepp.faceid.api_key=27f41b5fcdc5f29a6f35ab39ff85f0aae8f0d43ebb4978ab63d90ab6fb1b1a932d4858c8b993c23dec575e72aa68c983
+$$.$facepp.faceid.api_secret=18bd284cd1f23aa7f0d6ba4102be9dddfea64a59192d987d6b62a2f29cc3ec19895f4cea0e3c51ef4768bd0f68f9f60e
+
+#mongodb
+mguri.username=exam-cloud-dev
+mguri.password=Examcloud123
+mguri.hostAndPortGroup=dds-wz972dde5d2d78e433270.mongodb.rds.aliyuncs.com:3717
+mguri.database=admin
+mguri.maxPoolSize=50
+
+spring.data.mongodb.uri=mongodb://${mguri.username}:${mguri.password}@${mguri.hostAndPortGroup}/${mguri.database}?maxPoolSize=${mguri.maxPoolSize}&maxIdleTimeMS=6000
+
+#baidu
+$$.$baidu.apiKey=197558fa1110c3534e0fe4dd96764ae135b81479296efcdc912954daebc37071
+$$.$baidu.secretKey=6ef631b0775a4a4ebe70cd5b7dde00e4174f8e490e728769fd814ed71ca979ae8f7a2a51bf62481dae4048d75b15ecbc
+
+#tomcat
+server.tomcat.uri-encoding=UTF-8
+server.tomcat.max-threads=10
+server.tomcat.min-spare-threads=1
+server.tomcat.accept-count=10
+server.tomcat.max-connections=100
+
+spring.mvc.async.request-timeout=1000000000
+
+examcloud.api.flowLimited.allowedRate=10
+examcloud.api.flowLimited.minCallRate=10
+examcloud.api.permitsPerSecond=8000
+
+# mq
+$report.enable=false
+#$report.mq-type=kafka
+#$kafka-bootstrap-servers=192.168.10.39:9092

+ 32 - 0
src/main/resources/log4j2.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN" monitorInterval="30">
+	<Appenders>
+		<!-- 控制台 日志 -->
+		<Console name="Console" target="SYSTEM_OUT">
+			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}| %level | %X{TRACE_ID} - %X{CALLER} | %m | %l%n" />
+		</Console>
+		<!-- debug 日志 -->
+		<RollingFile name="DEBUG_APPERDER" fileName="./logs/debug/debug.log" filePattern="./logs/debug/debug-%d{yyyy.MM.dd.HH}-%i.log">
+			<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}| %level | %X{TRACE_ID} - %X{CALLER} | %m | %l%n" />
+			<Policies>
+				<SizeBasedTriggeringPolicy size="100 MB" />
+			</Policies>
+			<DefaultRolloverStrategy max="10000">
+			</DefaultRolloverStrategy>
+		</RollingFile>
+	</Appenders>
+
+	<Loggers>
+		<Logger name="cn.com.qmth" level="debug" additivity="false">
+			<AppenderRef ref="DEBUG_APPERDER" />
+			<AppenderRef ref="Console" />
+		</Logger>
+
+
+		<Root level="INFO">
+			<AppenderRef ref="Console" />
+			<AppenderRef ref="DEBUG_APPERDER" />
+		</Root>
+	</Loggers>
+
+</Configuration>