多线程以及主线程等待并发子线程运行
2013-11-22 15:05
337 查看
首先,用到的线程类有CountDownLatch。进行子线程的计数的。子线程中run最后面调用countDownLatch.countDown();方法,该子线程执行完后便减一,主线程中子线程的start后调用cDownLatch.await();方法,实现主线程等待并发子线程。
以下代码是实现多线程进行一个文件的读写,相当于复制了。目的是为实现多线程并发,虽然速度上还有点欠缺。
先是主程序代码
下面是子线程
下面是子线程
以下代码是实现多线程进行一个文件的读写,相当于复制了。目的是为实现多线程并发,虽然速度上还有点欠缺。
先是主程序代码
package com.filethread; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CountDownLatch; public class ReadFileMain { static FileThread[] fThread; static long startTime; final static String OUT_FILE_NAME = "C:\\Users\\dandan\\Desktop\\卑鄙的我2.神偷奶爸2.DVD中字-cut.rmvb"; /** * @param args */ public static void main(String[] args) { final int DOWN_THREAD_NUM = 4; final String READ_FILE = "C:\\Users\\dandan\\Desktop\\svn\\卑鄙的我2.神偷奶爸2.DVD中字-cut.rmvb"; InputStream[] isArrInputStreams = new InputStream[DOWN_THREAD_NUM]; RandomAccessFile[] outArrAccessFiles = new RandomAccessFile[DOWN_THREAD_NUM]; try { isArrInputStreams[0] = new FileInputStream(READ_FILE); long fileLen = getFileLength(new File(READ_FILE)); System.out.println("文件的大小" + fileLen); //以输出文件名创建第一个RandomAccessFile输出流 outArrAccessFiles[0] = new RandomAccessFile(OUT_FILE_NAME, "rw"); //创建一个与文件相同大小的空文件 for (int i = 0; i < fileLen / 1024; i++) { try { outArrAccessFiles[0].write(1024); // System.out.println(i+ "------" + fileLen / 1024 + "相差:" + (fileLen / 1024 - i)); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } //每线程应该读取的字节数 long numPerthread = fileLen / DOWN_THREAD_NUM; startTime = System.currentTimeMillis(); System.out.println(new SimpleDateFormat("yy-MM-DD HH:MM:SS").format(new Date())); //整个文件整除后剩下的余数 long end = fileLen % DOWN_THREAD_NUM; fThread = new FileThread[DOWN_THREAD_NUM]; CountDownLatch cDownLatch = new CountDownLatch(DOWN_THREAD_NUM); for (int i = 0; i < DOWN_THREAD_NUM; i++) { FileThread f2 = null; //为每个线程打开一个输入流、一个RandomAccessFile对象, //让每个线程分别负责读取文件的不同部分。 if (i != 0) { isArrInputStreams[i] = new FileInputStream(READ_FILE); //以指定输出文件创建多个RandomAccessFile对象 outArrAccessFiles[i] = new RandomAccessFile(OUT_FILE_NAME, "rw"); } if (i == DOWN_THREAD_NUM - 1) { //最后一个线程读取指定numPerThred+left个字节 f2 = new FileThread(i * numPerthread, (i+1) * numPerthread + end, isArrInputStreams[i], outArrAccessFiles[i],cDownLatch); }else { //每个线程负责读取一定的numPerThred个字节 f2 = new FileThread(i * numPerthread, (i + 1) * numPerthread, isArrInputStreams[i], outArrAccessFiles[i],cDownLatch); } f2.start(); fThread[i] = f2; } /** //判断所有子线程是否执行完毕, int size = fThread.length; // while(true){ for (int i = 0; i < size;) { if (fThread[i] != null && fThread[i].getState() == Thread.State.TERMINATED) { fThread[i] = null;size--; } if(fThread[i] != null && fThread[i].getState() == Thread.State.RUNNABLE) System.out.println(fThread[i].getId() + "存活中"); if(size == 0) warrting();break; } // } */ try { cDownLatch.await(); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } warrting(); } catch (FileNotFoundException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } public static void warrting() { System.out.println("开始读取:时间---" + ReadFileMain.startTime); long endTime = System.currentTimeMillis(); System.out.println("读取完毕:时间---" + endTime); System.out.println("耗时:" + (endTime - ReadFileMain.startTime)); System.out.println(new File(ReadFileMain.OUT_FILE_NAME).length()); System.out.println(new SimpleDateFormat("yy-MM-DD HH:MM:SS").format(new Date())); } public static long getFileLength(File file) { // long length = 0; // //获取文件的长度 // long size = file.length(); // length = size; // return length; return file.length(); } }
下面是子线程
下面是子线程
package com.filethread; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.util.Date; import java.util.concurrent.CountDownLatch; public class FileThread extends Thread { /** * 十个线程读取一个文本文件 * 创建一个线程类,读取文件,读取方法中,返回读取到的位置,下一个线程继续时读取上一个线程读取到的末尾处。 */ //定义字节数组(取水的竹筒)的长度 private final int BUFF_LEN = 1023; //定义读取的起始点 //定义读取的结束点 private long start,end; //读取文件对应的输入流 private InputStream iStream; //将读取到的字节输出到raf中 private RandomAccessFile rat; CountDownLatch countDownLatch; //构造器,传入输入流,输出流和读取起始点、结束点 public FileThread(long start,long end,InputStream is,RandomAccessFile rat,CountDownLatch cd){ //输出该线程负责读取的字节位置 System.out.println(start + "***********" + end); this.start = start; this.end = end; this.iStream = is; this.rat = rat; this.countDownLatch = cd; } public void run() { System.out.println(this.getId() + "----" + System.currentTimeMillis() + "++++" + new Date()); try { iStream.skip(start); rat.seek(start); //定义读取输入流内容的的缓存数组(竹筒) byte[] buff = new byte[BUFF_LEN]; //本线程负责读取文件的大小 long contenleng = end - start; //定义最多需要读取几次就可以完成本线程的读取 long tim = contenleng / BUFF_LEN + 4; //实际读取的字节数 int hasRead = 0; for (int i = 0; i < tim; i++) { hasRead = iStream.read(buff); //如果读取的字节数小于0,则退出循环! if(hasRead < 0) break; rat.write(buff,0,hasRead); } } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } //使用finally块来关闭当前线程的输入流、输出流 finally{ try { if(iStream != null) iStream.close(); if (rat != null) rat.close(); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } countDownLatch.countDown(); System.out.println("countDownLatch.getCount():" + countDownLatch.getCount()); System.out.println(this.getId() + "----" + System.currentTimeMillis() + "++++" + new Date()); } }
相关文章推荐
- 并发问题和主线程等待所有子线程运行完毕再执行
- java 多线程 主线程等待 子线程序列、并发结果
- 一个不错的线程讲解系列,记录下来以便学习(最近研究多线程以及并发)
- 多个子线程并发执行,主线程等待所有子线程都结束后再继续运行
- 主线程等待子线程运行完之后再运行
- boost中asio网络库多线程并发处理实现,以及asio在多线程模型中线程的调度情况和线程安全。
- Java多线程--让主线程等待所有子线程执行完毕
- 多线程实现闹钟功能以及主线程与子线程的关系说明
- Java多线程--让主线程等待所有子线程执行完毕(转)
- Java多线程--让主线程等待所有子线程执行完毕
- C++类的静态成员函数在多线程的工作机制以及运行过程中强制结束线程实验
- Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束
- (13)多线程与并发库之java5阻塞队列(BlockingQueue)的应用----子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程循环100次,如此循环50次
- boost中asio网络库多线程并发处理实现,以及asio在多线程模型中线程的调度情况和线程安全。
- Java多线程--让主线程等待所有子线程执行完毕
- C# 多线程join的用法,等待多个子线程结束后再执行主线程
- java多线程实现主线程等待所有子线程执行完毕
- [置顶] [转]Java多线程--让主线程等待所有子线程执行完毕
- java线程一之创建线程、线程池以及多线程运行时间统计
- java多线程-线程运行状态-获取线程对象以及名称