29多线程(线程池定时器)将一个文件复制多次拆分文件并合并多线程复制文件
Posted ShawnYue-08
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了29多线程(线程池定时器)将一个文件复制多次拆分文件并合并多线程复制文件相关的知识,希望对你有一定的参考价值。
线程池
程序启动一个新线程成本是比较高的,因为它涉及到与操作系统交互。而使用线程池可以很好的提高性能,尤其是
当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK 5之前,我们必须手动实现自己的线程池,从JDK 5开始,Java内置支持线程池。
package org.westos.demo;
import java.util.concurrent.*;
/**
* @author lwj
* @date 2020/6/7 8:36
*/
public class MyTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*
线程池:容器,存有一定数量线程对象的容器
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool(): 根据任务的数量来创建线程对应的线程个数
public static ExecutorService newFixedThreadPool(int nThreads): 固定初始化几个线程
public static ExecutorService newSingleThreadExecutor(): 初始化一个线程的线程池
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池
*/
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程执行了这个任务");
}
});
//根据任务数量创建相应数量的线程对象
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("提交第二个任务");
}
});
Future<Integer> submit = executorService.submit(new MyCallable());
System.out.println(submit.get());
executorService.shutdown();
//关闭线程池
}
}
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 100;
}
}
package org.westos.demo2;
import java.util.concurrent.*;
/**
* @author lwj
* @date 2020/6/7 8:36
*/
public class MyTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*
线程池:容器,存有一定数量线程对象的容器
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool(): 根据任务的数量来创建线程对应的线程个数
public static ExecutorService newFixedThreadPool(int nThreads): 固定初始化几个线程
public static ExecutorService newSingleThreadExecutor(): 初始化一个线程的线程池
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池
*/
ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
executorService.shutdown();
}
}
package org.westos.demo3;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author lwj
* @date 2020/6/7 8:36
*/
public class MyTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*
线程池:容器,存有一定数量线程对象的容器
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool(): 根据任务的数量来创建线程对应的线程个数
public static ExecutorService newFixedThreadPool(int nThreads): 固定初始化几个线程
public static ExecutorService newSingleThreadExecutor(): 初始化一个线程的线程池
这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)
使用步骤:
创建线程池对象
创建Runnable实例
提交Runnable实例
关闭线程池
*/
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
executorService.shutdown();
}
}
定时器与定时任务
package org.westos.demo4;
import java.util.Timer;
import java.util.TimerTask;
/**
* 定时器
* @author lwj
* @date 2020/6/7 9:28
*/
public class MyTest {
public static void main(String[] args) {
Timer timer = new Timer();
//TimerTask抽象类
MyTimerTask myTimerTask = new MyTimerTask(timer);
timer.schedule(myTimerTask, 3000);
//等3s后执行该定时任务
// 取消定时器
// timer.cancel();
}
}
class MyTimerTask extends TimerTask {
public Timer timer;
public MyTimerTask(Timer timer) {
this.timer = timer;
}
@Override
public void run() {
System.out.println("时间到了");
timer.cancel();
}
}
package org.westos.demo4;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author lwj
* @date 2020/6/7 9:36
*/
public class MyTest2 {
public static void main(String[] args) {
Timer timer = new Timer();
MyTimerTask2 myTimerTask2 = new MyTimerTask2();
timer.schedule(myTimerTask2, 3000, 1000);
//等3s后执行此任务,以后间隔1s重复执行定时任务
}
}
class MyTimerTask2 extends TimerTask {
@Override
public void run() {
System.out.println("时间到了");
}
}
package org.westos.demo4;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author lwj
* @date 2020/6/7 9:38
*/
public class MyTest3 {
public static void main(String[] args) throws ParseException {
Timer timer = new Timer();
MyTimerTask3 myTimerTask3 = new MyTimerTask3();
//myTimerTask2.cancel(); 取消定时任务
String str = "2020-06-07 09:49:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date parse = sdf.parse(str);
timer.schedule(myTimerTask3, parse);
//指定某个时间执行定时任务
}
}
class MyTimerTask3 extends TimerTask {
@Override
public void run() {
System.out.println("时间到了");
}
}
指定时间删除文件夹
package org.westos.demo4;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
/**
* 定时删除一个文件夹
* @author lwj
* @date 2020/6/7 9:49
*/
public class MyDemo {
public static void main(String[] args) {
Timer timer = new Timer();
//定时器
File source = new File("E:\\新建文件夹");
TimerTaskDemo timerTaskDemo = new TimerTaskDemo(source, timer);
timer.schedule(timerTaskDemo, 5000);
//延迟5s后执行定时任务,删除文件夹
}
}
class TimerTaskDemo extends TimerTask {
public File directory;
public Timer timer;
public TimerTaskDemo(File directory, Timer timer) {
this.directory = directory;
this.timer = timer;
}
@Override
public void run() {
//删除文件夹并关闭定时器
deleteDir(directory);
timer.cancel();
//取消定时器
}
public void deleteDir(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File file1 : files) {
deleteDir(file1);
}
}
file.delete();
//删除文件或者空文件夹
}
}
练习题
1、把一个文件复制多次
package org.westos.demo5;
import java.io.*;
/**
* @author lwj
* @date 2020/6/7 15:11
*/
public class MyTest {
public static void main(String[] args) throws IOException {
File source = new File("C:\\Users\\shawn\\Music\\MV\\G.E.M. 邓紫棋-我说了算(多芬秀发合作单曲)(蓝光).mp4");
RandomAccessFile rw = new RandomAccessFile(source, "rw");
byte[] bytes = new byte[1024 * 8];
int len = 0;
for (int i = 0; i < 3; i++) {
FileOutputStream fos = new FileOutputStream(new File("E:\\music", "G.E.M" + i + ".mp4"));
while ((len = rw.read(bytes)) != -1) {
fos.write(bytes, 0, len);
fos.flush();
}
fos.close();
//每复制一个文件,将随机读取流的指针重置为0
rw.seek(0);
}
rw.close();
}
}
2、拆分文件并合并
package org.westos.demo5;
import java.io.*;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Vector;
/**
* @author lwj
* @date 2020/6/7 15:24
*/
public class MyTest2 {
public static void main(String[] args) throws IOException {
split();
merge();
}
private static void merge() throws IOException {
File source = new File(".");
System.out.println(source.getAbsolutePath());
File[] files = source.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isFile() && pathname.length() <= 1024 * 1024 && pathname.getName().endsWith(".mp3");
}
});
Vector<FileInputStream> vector = new Vector<>();
for (File file : files) {
vector.addElement(new FileInputStream(file));
}
Enumeration<FileInputStream> elements = vector.elements();
SequenceInputStream sis = new SequenceInputStream(elements);
byte[] bytes = new byte[1024];
int len = 0;
FileOutputStream fos = new FileOutputStream(new File("百事.mp3"));
while ((len = sis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
fos.flush();
}
fos.close();
sis.close();
}
private static void split() throws IOException {
//把一份文件拆分为多份,每份1M,然后合并
File source = new File("C:\\Users\\shawn\\Music\\G.E.M. 邓紫棋 _ 王嘉尔 - 热爱就一起.mp3");
FileInputStream fis = new FileInputStream(source);
byte[] bytes = new byte[1024 * 1024];
int len = 0;
int index = 0;
while ((len = fis.read(bytes)) != -1) {
FileOutputStream fos = new FileOutputStream(new File(index++ + ".mp3"));
fos.write(bytes, 0, len);
fos.close();
}
fis.close();
}
}
3、多线程复制文件
package org.westos.demo5;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* @author lwj
* @date 2020/6/7 15:49
*/
public class MyDemo {
public static void main(String[] args) throws FileNotFoundException {
//多线程复制同一份文件
File source = new File("C:\\Users\\shawn\\Music\\G.E.M. 邓紫棋 _ 王嘉尔 - 热爱就一起.mp3");
File destFile = new File(".\\邓紫棋-热爱就一起.mp3");
long length = source.length();
//文件的总大小
long threadNums = 3;
long average = length / threadNums;
for (int i = 0; i < 3; i++) {
long start = i * (average + 1);
long end = (i + 1) * average;
new CopyFileThread(start, end, source, destFile).start();
}
//如果3个线程不能均分,那么再添加一个线程
if (length % threadNums != 0) {
long start = threadNums * average + 1;
new CopyFileThread(start, length, source, destFile).start();
}
}
}
class CopyFileThread extends Thread {
public long start;
public long end;
public RandomAccessFile in;
public RandomAccessFile out;
public CopyFileThread(long start, long end, File srcFile, File destFile) throws FileNotFoundException {
this.start = start;
this.end = end;
this.in = new RandomAccessFile(srcFile, "rw");
this.out = new RandomAccessFile(destFile, "rw");
}
@Override
public void run() {
try {
in.seek(start);
out.seek(start);
//设置读写起始指针
byte[] bytes = new byte[1024 * 8];
int len = 0;
long pointer = in.getFilePointer();
while (pointer <= end && (len = in.read(bytes)) != -1) {
//最后一次有可能只剩余1KB,然而最后一次还是会读取8KB,然后pointer > end退出while
out.write(bytes, 0, len);
pointer += len;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上是关于29多线程(线程池定时器)将一个文件复制多次拆分文件并合并多线程复制文件的主要内容,如果未能解决你的问题,请参考以下文章