当前位置:   article > 正文

java 视频统一转成mp4格式,并且异步多线程上传_各种格式视频转化为mp4. java

各种格式视频转化为mp4. java

背景:遇到一个项目就是上传视频文件不限格式,需要全部统一转成mp4格式。具体细节是 1.前端展示的视频不能是从头加载的,需要像某讯那样快进到哪里,从哪个节点开始加载,实现无卡顿播放,2,后台获取时长,大小等数据信息,四张视频截图封面,从其中选择一张作为封面。

直接上代码:视频获取时长大小,截图,视频转换

  1. import com.alibaba.fastjson.JSONObject;
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.nio.charset.StandardCharsets;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import java.util.regex.Matcher;
  10. import java.util.regex.Pattern;
  11. public class ConvertVideo {
  12. private static String mplayerPath; //= "C:/watermark/mencoder.exe";
  13. private static String ffmpegPath; //= "C:/watermark/ffmpeg-4.3.1-2021-01-01-essentials_build/bin/ffmpeg.exe";
  14. private static String filepath; //= "D:/minio/data/";
  15. public static void setMplayerPath(String mplayerPath) {
  16. ConvertVideo.mplayerPath = mplayerPath;
  17. }
  18. public static void setFfmpegPath(String ffmpegPath) {
  19. ConvertVideo.ffmpegPath = ffmpegPath;
  20. }
  21. public static void setFilepath(String filepath) {
  22. ConvertVideo.filepath = filepath;
  23. }
  24. /**
  25. * 视频格式转换入口
  26. *
  27. * @param inputPath 源文件 路径
  28. * @param outputPath 目标文件 路径
  29. * @param outputPath1 中间文件地址 路径
  30. * @return
  31. */
  32. public synchronized static boolean process(String inputPath, String outputPath ,String outputPath1) {
  33. int type = checkContentType(inputPath);
  34. boolean status = false;
  35. Long old = System.currentTimeMillis();
  36. System.out.println("old--------" + old);
  37. if (type == 0) {
  38. System.out.println("直接转成MP4格式");
  39. status = processMP4(inputPath, outputPath);// 直接转成flv格式
  40. } else if (type == 1) {
  41. String avifilepath = processAVI(inputPath, outputPath1);
  42. System.out.println(avifilepath);
  43. if (avifilepath == null){
  44. return false;// 没有得到avi格式
  45. }
  46. status = processMP4(avifilepath, outputPath);// 将avi转成flv格式
  47. }
  48. Long yong = System.currentTimeMillis();
  49. System.out.println("消耗时间----------" + (yong-old));
  50. return status;
  51. }
  52. /**
  53. * 判断文件类型.执行不同的转换流程
  54. *
  55. * @param inputPath 源文件路径
  56. * @return
  57. */
  58. private static int checkContentType(String inputPath) {
  59. String type = inputPath.substring(inputPath.lastIndexOf(".") + 1, inputPath.length())
  60. .toLowerCase();
  61. // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
  62. if (type.equals("avi")) {
  63. return 0;
  64. } else if (type.equals("mpg")) {
  65. return 0;
  66. } else if (type.equals("wmv")) {
  67. return 0;
  68. } else if (type.equals("3gp")) {
  69. return 0;
  70. } else if (type.equals("mov")) {
  71. return 0;
  72. } else if (type.equals("mp4")) {
  73. return 0;
  74. } else if (type.equals("asf")) {
  75. return 0;
  76. } else if (type.equals("asx")) {
  77. return 0;
  78. } else if (type.equals("flv")) {
  79. return 0;
  80. }
  81. // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),
  82. // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
  83. else if (type.equals("wmv9")) {
  84. return 1;
  85. } else if (type.equals("rm")) {
  86. return 1;
  87. } else if (type.equals("rmvb")) {
  88. return 1;
  89. }else if (type.equals("dat")) {
  90. return 1;
  91. }
  92. return 9;
  93. }
  94. /**
  95. * 判断源文件是否存在
  96. *
  97. * @param path 文件路径
  98. * @return
  99. */
  100. private static boolean checkfile(String path) {
  101. File file = new File(path);
  102. if (!file.isFile()) {
  103. return false;
  104. }
  105. return true;
  106. }
  107. // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
  108. private static String processAVI(String inputPath, String outputPath1) {
  109. List<String> commend = new ArrayList<>();
  110. commend.add(mplayerPath);
  111. //commend.add("C:/watermark/mencoder.exe");
  112. commend.add(inputPath);
  113. commend.add("-oac");
  114. commend.add("mp3lame");
  115. commend.add("-lameopts");
  116. commend.add("preset=64");
  117. commend.add("-ovc");
  118. commend.add("xvid");
  119. commend.add("-xvidencopts");
  120. commend.add("bitrate=600");
  121. commend.add("-of");
  122. commend.add("avi");
  123. commend.add("-o");
  124. commend.add(outputPath1);
  125. try {
  126. ProcessBuilder builder = new ProcessBuilder();
  127. Process process = builder.command(commend).redirectErrorStream(true).start();
  128. new PrintStream(process.getInputStream()).start();
  129. new PrintStream(process.getErrorStream()).start();
  130. process.waitFor();
  131. process.destroy();
  132. return outputPath1;
  133. } catch (Exception e) {
  134. e.printStackTrace();
  135. return null;
  136. }
  137. }
  138. // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) 转换为MP4
  139. private static boolean processMP4(String inputPath, String outputPath) {
  140. if (!checkfile(inputPath)) {
  141. System.out.println(inputPath + " is not file");
  142. return false;
  143. }
  144. List<String> command = new ArrayList<>();
  145. command.add(ffmpegPath);
  146. //command.add("C:/watermark/ffmpeg-4.3.1-2021-01-01-essentials_build/bin/ffmpeg.exe");
  147. command.add("-i");
  148. command.add(inputPath);
  149. command.add("-c:v");
  150. command.add("libx264");
  151. command.add("-mbd");
  152. command.add("0");
  153. command.add("-c:a");
  154. command.add("aac");
  155. command.add("-strict");
  156. command.add("-2");
  157. command.add("-pix_fmt");
  158. command.add("yuv420p");
  159. command.add("-movflags");
  160. command.add("faststart");
  161. command.add(outputPath);
  162. try {
  163. Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
  164. new PrintStream(videoProcess.getErrorStream()).start();
  165. new PrintStream(videoProcess.getInputStream()).start();
  166. videoProcess.waitFor();
  167. videoProcess.destroy();
  168. System.out.println(outputPath);
  169. return true;
  170. } catch (Exception e) {
  171. return false;
  172. }
  173. }
  174. //map4截取图片
  175. public synchronized static boolean processImg(String veido_path, String image_path,String minao) {
  176. File file = new File(veido_path);
  177. if (!file.exists()) {
  178. System.err.println("路径[" + veido_path + "]对应的视频文件不存在!");
  179. return false;
  180. }
  181. List<String> commands = new ArrayList<String>();
  182. commands.add(ffmpegPath);
  183. commands.add("-i");
  184. commands.add(veido_path);
  185. commands.add("-y");
  186. commands.add("-f");
  187. commands.add("image2");
  188. commands.add("-ss");
  189. System.out.println(String.valueOf(minao));
  190. commands.add(minao);// 这个参数是设置截取视频多少秒时的画面
  191. // commands.add("-t");
  192. // commands.add("0.001");
  193. commands.add("-s");
  194. commands.add("700x700");//尺寸
  195. /*commands.add(veido_path.substring(0, veido_path.lastIndexOf("."))
  196. .replaceFirst("vedio", "file") + ".jpg");*/
  197. commands.add(image_path);
  198. try {
  199. ProcessBuilder builder = new ProcessBuilder();
  200. builder.command(commands);
  201. builder.start();
  202. System.out.println("截取成功");
  203. return true;
  204. } catch (Exception e) {
  205. e.printStackTrace();
  206. return false;
  207. }
  208. }
  209. public static JSONObject readVideoTimeFromCommand(String filePath){
  210. JSONObject jsonObject = new JSONObject();
  211. ProcessBuilder builder = new ProcessBuilder();
  212. List<String> commands = new ArrayList<>();
  213. commands.add(ffmpegPath);
  214. commands.add("-i");
  215. commands.add(filePath);
  216. builder.command(commands);
  217. builder.redirectErrorStream(true);
  218. Process p = null;
  219. try {
  220. p = builder.start();
  221. } catch (IOException e) {
  222. e.printStackTrace();
  223. }
  224. // 获取执行输出信息
  225. BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
  226. StringBuilder outInfo = new StringBuilder();
  227. String line = "";
  228. while (true) {
  229. try {
  230. if (!((line = br.readLine()) != null)) {
  231. break;
  232. }
  233. } catch (IOException e) {
  234. e.printStackTrace();
  235. }
  236. outInfo.append(line);
  237. }
  238. try {
  239. br.close();
  240. } catch (IOException e) {
  241. e.printStackTrace();
  242. }
  243. // 通过正则获取时长信息
  244. String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
  245. Pattern pattern = Pattern.compile(regexDuration);
  246. Matcher matcher = pattern.matcher(outInfo.toString());
  247. if (matcher.find()) {
  248. return getTime(matcher.group(1));
  249. }
  250. return jsonObject;
  251. }
  252. /**
  253. * 获取时间毫秒
  254. * @param time 格式:"00:00:10.68"
  255. * @return
  256. */
  257. private static JSONObject getTime(String time) {
  258. JSONObject jsonObject = new JSONObject();
  259. System.out.println(time);
  260. int index = time.lastIndexOf(".");
  261. String distpath = time.substring(0, index);
  262. jsonObject.put("time",distpath);
  263. int min = 0;
  264. String[] strs = time.split(":");
  265. String ZERO="0";
  266. if (strs[0].compareTo(ZERO) > 0) {
  267. // 秒
  268. min += Long.parseLong(strs[0]) * 60 * 60 * 1000;
  269. }
  270. if (strs[1].compareTo(ZERO) > 0) {
  271. min += Long.parseLong(strs[1]) * 60 * 1000;
  272. }
  273. if (strs[2].compareTo(ZERO) > 0) {
  274. min += Math.round(Double.parseDouble(strs[2]) * 1000);
  275. }
  276. System.out.println(min);
  277. jsonObject.put("min",min);
  278. return jsonObject;
  279. }
  280. }
  281. /**
  282. * 资源释放流.避免内存溢出导致进程阻塞
  283. */
  284. class PrintStream extends Thread {
  285. java.io.InputStream __is = null;
  286. public PrintStream(java.io.InputStream is) {
  287. __is = is;
  288. }
  289. @Override
  290. public void run() {
  291. try {
  292. while (this != null) {
  293. int _ch = __is.read();
  294. if (_ch != -1){
  295. System.out.print((char) _ch);
  296. }else{
  297. break;
  298. }
  299. }
  300. __is.close();
  301. } catch (Exception e) {
  302. e.printStackTrace();
  303. }
  304. }
  305. public static String secondsToTime(int seconds){
  306. int h=seconds/3600; //小时
  307. int m=(seconds%3600)/60; //分钟
  308. int s=(seconds%3600)%60; //秒
  309. String hh = "";
  310. String mm = "";
  311. String ss = "";
  312. if(h>0){
  313. if(h<9){
  314. hh = "0"+h;
  315. }else{
  316. hh = ""+h;
  317. }
  318. if(m<9){
  319. mm = "0"+m;
  320. }else{
  321. mm = ""+m;
  322. }
  323. if(s<9){
  324. ss = "0"+s;
  325. }else{
  326. ss = ""+s;
  327. }
  328. return hh+":"+mm+":"+ss;
  329. }
  330. if(m>0){
  331. if(m<9){
  332. mm = "0"+m;
  333. }else{
  334. mm = ""+m;
  335. }
  336. if(s<9){
  337. ss = "0"+s;
  338. }else{
  339. ss = ""+s;
  340. }
  341. return "00:"+mm+":"+ss;
  342. }
  343. if(s<9){
  344. ss = "0"+s;
  345. }else{
  346. ss = ""+s;
  347. }
  348. return "00:00:"+ss;
  349. }
  350. public static void main(String[] args) {
  351. //获取时长和大小
  352. ConvertVideo.readVideoTimeFromCommand("文件路径");
  353. //截图 最后一个参数需要是 00:00:00格式的 截图最好截图前10秒的图,要不然截图会不成功
  354. // ConvertVideo.processImg("源文件", "图片存放位置" + ".jpg", secondsToTime("视频文件大小"));//截图
  355. //视频转换
  356. // ConvertVideo.process("源文件路径", "转成的mp4文件路径", "中间avi临时文件路径");
  357. }
  358. }

注:需要用到两个文件

链接:https://pan.baidu.com/s/1qZb7CqcUxTZDe-nYwsnWsQ 
提取码:abcd

链接:https://pan.baidu.com/s/1oPzD1ZNCgF3HCKfi8aTEzg 
提取码:abcd

注意这种转换不管是获取时长,截图还是视频转换如果是多线程执行的话,一个线程执行完成另一个线程才会被执行,相当于多线程没有啥用,但是转换太费时间了,所以获取时长和截图我又找了其他的方法

上代码:

  1. import org.apache.commons.io.FileUtils;
  2. import org.springframework.web.multipart.MultipartFile;
  3. import ws.schild.jave.MultimediaObject;
  4. import ws.schild.jave.info.MultimediaInfo;
  5. import java.io.File;
  6. import java.text.SimpleDateFormat;
  7. import java.util.TimeZone;
  8. public class VideoUtil {
  9. /**
  10. * 上传视频,获取视频时长,返回毫秒
  11. * @param multipartFile
  12. * @return
  13. */
  14. public static long getDurationBackMillis(MultipartFile multipartFile){
  15. if(multipartFile != null){
  16. try{
  17. // 根据上传的文件名字,构建初始化的文件对象(临时文件),这个文件是空的
  18. File file = new File(multipartFile.getOriginalFilename());
  19. // 通过工具类,将文件拷贝到空的文件对象中
  20. FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
  21. // 将普通文件对象转换为媒体对象
  22. MultimediaObject multimediaObject = new MultimediaObject(file);
  23. // 获取媒体对象的信息对象
  24. MultimediaInfo info = multimediaObject.getInfo();
  25. // 从媒体信息对象中获取媒体的时长,单位是:ms
  26. long duration = info.getDuration();
  27. // 删除临时文件
  28. file.delete();
  29. return duration;
  30. } catch(Exception e){
  31. return 0L;
  32. }
  33. }
  34. return 0L;
  35. }
  36. /**
  37. * 上传视频,获取视频时长,返回时分秒字符串
  38. * @param multipartFile
  39. * @return
  40. */
  41. public static String getDurationBackString(MultipartFile multipartFile){
  42. // 获取视频时长,返回毫秒
  43. long duration = getDurationBackMillis(multipartFile);
  44. // 毫秒转时分秒的转换
  45. // 日期格式化对象,给时分秒格式
  46. SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
  47. // 这里很重要,如果不设置时区的话,输出结果就会是几点钟,而不是毫秒值对应的时分秒数量了。
  48. formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
  49. // 毫秒转化为字符串
  50. return formatter.format(duration);
  51. }
  52. }
  1. import org.bytedeco.javacpp.opencv_core;
  2. import org.bytedeco.javacv.FFmpegFrameGrabber;
  3. import org.bytedeco.javacv.Frame;
  4. import org.bytedeco.javacv.FrameGrabber;
  5. import sun.misc.BASE64Encoder;
  6. import javax.imageio.ImageIO;
  7. import java.awt.*;
  8. import java.awt.image.BufferedImage;
  9. import java.io.ByteArrayOutputStream;
  10. import java.io.File;
  11. import java.io.IOException;
  12. public class DealVideo {
  13. /*默认图片格式 jpg*/
  14. public static String DEFAULT_IMG_FORMAT = "jpg";
  15. /**
  16. * 获取指定视频的帧并保存为图片JPG格式至指定文件
  17. *
  18. * @param videoFile 源视频文件路径
  19. * @param targetFile 截取帧的图片存放路径
  20. * @param frameNum 截取第几帧
  21. * @throws Exception
  22. */
  23. public static void fetchFrameToFile(String videoFile, String targetFile, int frameNum) {
  24. //校验输入和输出
  25. checkInAnOut(videoFile, targetFile);
  26. try {
  27. File frameFile = new File(targetFile);
  28. FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
  29. ff.start();
  30. int length = ff.getLengthInFrames();
  31. /*第几帧判断设置*/
  32. if (frameNum < 0) {
  33. frameNum = 0;
  34. }
  35. if (frameNum > length) {
  36. frameNum = length - 5;
  37. }
  38. //指定第几帧
  39. ff.setFrameNumber(frameNum);
  40. int i = 0;
  41. Frame f = null;
  42. while (i < length) {
  43. // 过滤前5帧,避免出现全黑的图片,依自己情况而定
  44. f = ff.grabFrame();
  45. if ((i >= 5) && (f.image != null)) {
  46. break;
  47. }
  48. i++;
  49. }
  50. opencv_core.IplImage img = f.image;
  51. int width = img.width();
  52. int height = img.height();
  53. BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
  54. bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
  55. 0, 0, null);
  56. ff.flush();
  57. ff.stop();
  58. ImageIO.write(bi, DEFAULT_IMG_FORMAT, frameFile);
  59. } catch (Exception e) {
  60. //throw new RuntimeException("转换视频图片异常");
  61. e.printStackTrace();
  62. }
  63. }
  64. /**
  65. * 获取指定视频的帧并保存为图片自定义类型至指定文件
  66. *
  67. * @param videoFile 源视频文件路径
  68. * @param targetFile 截取帧的图片存放文件路径
  69. * @param outImgFormat 输出图片格式
  70. * @param frameNum 截取第几帧
  71. * @throws Exception
  72. */
  73. /* public static void fetchFrameToFile(String videoFile, String targetFile, String outImgFormat, int frameNum) throws FrameGrabber.Exception, IOException {
  74. //校验输入和输出
  75. checkInAnOut(videoFile, targetFile);
  76. try {
  77. File frameFile = new File(targetFile);
  78. FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
  79. ff.start();
  80. int length = ff.getLengthInFrames();
  81. *//*第几帧判断设置*//*
  82. if (frameNum < 0) {
  83. frameNum = 0;
  84. }
  85. if (frameNum > length) {
  86. frameNum = length - 5;
  87. }
  88. //指定第几帧
  89. ff.setFrameNumber(frameNum);
  90. int i = 0;
  91. Frame f = null;
  92. while (i < length) {
  93. // 过滤前5帧,避免出现全黑的图片,依自己情况而定
  94. f = ff.grabFrame();
  95. if ((i >= 5) && (f.image != null)) {
  96. break;
  97. }
  98. i++;
  99. }
  100. opencv_core.IplImage img = f.image;
  101. int width = img.width();
  102. int height = img.height();
  103. BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
  104. bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
  105. 0, 0, null);
  106. ff.flush();
  107. ff.stop();
  108. // ImageUtils2 工具类旋转图片
  109. BufferedImage ret = ImageUtils2.rotateClockwise0(bi);
  110. ImageIO.write(ret, outImgFormat, frameFile);
  111. } catch (Exception e) {
  112. throw new RuntimeException("转换视频图片异常");
  113. }
  114. }*/
  115. /**
  116. * 获取指定视频的帧图片,并转换为base64字符串
  117. *
  118. * @param videoFile 源视频文件路径
  119. * @param frameNum 截取第几帧
  120. * @throws Exception
  121. */
  122. public static String fetchFrameToBase64(String videoFile, int frameNum) throws FrameGrabber.Exception, IOException {
  123. //校验输入
  124. checkVideoFile(videoFile);
  125. try (ByteArrayOutputStream output = new ByteArrayOutputStream();) {
  126. FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
  127. ff.start();
  128. int length = ff.getLengthInFrames();
  129. /*第几帧判断设置*/
  130. if (frameNum < 0) {
  131. frameNum = 0;
  132. }
  133. if (frameNum > length) {
  134. frameNum = length - 5;
  135. }
  136. //指定第几帧
  137. ff.setFrameNumber(frameNum);
  138. int i = 0;
  139. Frame f = null;
  140. while (i < length) {
  141. // 过滤前5帧,避免出现全黑的图片,依自己情况而定
  142. f = ff.grabFrame();
  143. if ((i >= 5) && (f.image != null)) {
  144. break;
  145. }
  146. i++;
  147. }
  148. opencv_core.IplImage img = f.image;
  149. int width = img.width();
  150. int height = img.height();
  151. BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
  152. bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
  153. 0, 0, null);
  154. ImageIO.write(bi, DEFAULT_IMG_FORMAT, output);
  155. // 这里需要获取图片的base64数据串,所以将图片写到流里面
  156. ff.flush();
  157. ff.stop();
  158. return new BASE64Encoder().encode(output.toByteArray());
  159. } catch (Exception e) {
  160. throw new RuntimeException("转换视频图片异常");
  161. }
  162. }
  163. /**
  164. * 校验输入输出
  165. *
  166. * @param videoFile
  167. * @param targetFile
  168. */
  169. public static void checkInAnOut(String videoFile, String targetFile) {
  170. checkVideoFile(videoFile);
  171. checkTargetFileDir(targetFile);
  172. }
  173. /**
  174. * 验证文件目录是否存在,不存在就创建
  175. *
  176. * @param targetFile 文件路径
  177. * @return
  178. */
  179. public static void checkTargetFileDir(String targetFile) {
  180. String dirPath = targetFile.substring(0, targetFile.lastIndexOf(File.separator) + 1);
  181. File dir = new File(dirPath);
  182. if (!dir.exists()) {
  183. dir.mkdirs();
  184. }
  185. }
  186. /**
  187. * 检验文件是否存在
  188. *
  189. * @param videoFile
  190. */
  191. public static void checkVideoFile(String videoFile) {
  192. File file = new File(videoFile);
  193. if (!file.exists()) {
  194. throw new RuntimeException("文件不存在");
  195. }
  196. }
  197. }

我上传的代码demo大概代码

  1. //先上传源文件到系统
  2. savePath = CommonUtils.upload(file, bizPath, uploadType,sy);
  3. //获取源文件的时长和大小以及截图
  4. //时长
  5. String durationBackString = VideoUtil.getDurationBackString(file);
  6. //大小
  7. long durationBackMillis = VideoUtil.getDurationBackMillis(file);
  8. //截图
  9. DealVideo.fetchFrameToFile(inputPath,distpath + newnames + ".jpg",i1);
  10. //异步转换
  11. task.task1(inputPath, outputPath, outputPath1, uuid);

异步线程池

  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.core.task.TaskExecutor;
  4. import org.springframework.scheduling.annotation.EnableAsync;
  5. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  6. import java.util.concurrent.ThreadPoolExecutor;
  7. @Configuration
  8. @EnableAsync
  9. public class ThreadPoolConfig {
  10. /**
  11. * 每秒需要多少个线程处理?
  12. * tasks/(1/taskcost)
  13. */
  14. private int corePoolSize = 3;
  15. /**
  16. * 线程池维护线程的最大数量
  17. * (max(tasks)- queueCapacity)/(1/taskcost)
  18. */
  19. private int maxPoolSize = 100;
  20. /**
  21. * 缓存队列
  22. * (coreSizePool/taskcost)*responsetime
  23. */
  24. private int queueCapacity = 10;
  25. /**
  26. * 允许的空闲时间
  27. * 默认为60
  28. */
  29. private int keepAlive = 100;
  30. @Bean
  31. public TaskExecutor taskExecutor() {
  32. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  33. // 设置核心线程数
  34. executor.setCorePoolSize(corePoolSize);
  35. // 设置最大线程数
  36. executor.setMaxPoolSize(maxPoolSize);
  37. // 设置队列容量
  38. executor.setQueueCapacity(queueCapacity);
  39. // 设置允许的空闲时间(秒)
  40. //executor.setKeepAliveSeconds(keepAlive);
  41. // 设置默认线程名称
  42. executor.setThreadNamePrefix("thread-");
  43. // 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务
  44. // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
  45. executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  46. // 等待所有任务结束后再关闭线程池
  47. executor.setWaitForTasksToCompleteOnShutdown(true);
  48. return executor;
  49. }
  50. }

在启动类加上异步

 异步任务代码

  1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.jeecg.common.util.ConvertVideo;
  4. import org.jeecg.common.util.FileUrlUtil;
  5. import org.jeecg.common.util.MinioUtil;
  6. import org.jeecg.modules.business.num.entity.YwVisit;
  7. import org.jeecg.modules.business.num.service.IYwVisitService;
  8. import org.jeecg.modules.business.video.entity.YwVideo;
  9. import org.jeecg.modules.business.video.service.IYwVideoService;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.scheduling.annotation.Async;
  12. import org.springframework.scheduling.annotation.AsyncResult;
  13. import org.springframework.stereotype.Component;
  14. import org.springframework.util.concurrent.ListenableFuture;
  15. import java.util.Random;
  16. @Component
  17. @Slf4j
  18. public class MyTask {
  19. @Autowired
  20. private IYwVideoService videoService;
  21. @Autowired
  22. private IYwVisitService ywVisitService;
  23. @Async("taskExecutor")
  24. public synchronized void task1(String inputPath,String outputPath,String outputPath1,String uuid) throws Exception {
  25. System.out.println("正在执行线程" + Thread.currentThread().getName() + " 执行异步任务一"+uuid);
  26. boolean process = ConvertVideo.process(inputPath, outputPath, outputPath1);
  27. System.out.println("转换完成");
  28. YwVideo video = videoService.getOne(new QueryWrapper<YwVideo>()
  29. .eq("uuid", uuid)
  30. );
  31. if(null!=video){
  32. if(!process){
  33. video.setFlag("2");
  34. //根据uuid 更新状态
  35. //throw new Exception("转换错误");
  36. }else{
  37. video.setFlag("1");
  38. }
  39. //根据uuid更新状态
  40. videoService.updateById(video);
  41. }else{
  42. YwVisit visit = new YwVisit();
  43. visit.setUuid(uuid);
  44. ywVisitService.save(visit);
  45. }
  46. FileUrlUtil.removeObject(inputPath,"minio");
  47. FileUrlUtil.removeObject(outputPath1,"minio");
  48. }
  49. @Async("taskExecutor")
  50. public synchronized void test(int num) throws Exception {
  51. System.out.println("正在执行线程" + Thread.currentThread().getName() + " 执行异步任务"+num);
  52. }
  53. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/650494
推荐阅读
相关标签
  

闽ICP备14008679号