多线程那些糟糕的代码——你这样干过吗?
来源:互联网 发布:ip什么意思网络用语 编辑:程序博客网 时间:2024/05/17 04:40
最近在烦恼用java操作大文件的问题——如果我有一大堆数据在内存中,想要写入文件,如何提速?
我们都知道 Java 中的 RandomAccessFile 可以访问文件的任意位置 , 另外 , java 中想要提速的方法有缓存,多线程操作等。而在这一环节中我首先想到的就是多线程写入文件,这样可以提升速度的吧?
但是我们知道,无论何时文件的写操作,底层都会加锁(这会影响性能就不解释了),为了验证这个锁对多线程的影响有多大,下面做了一个实验,首先准备要写入文件的字符内容(500个字符):
int len = 500; int dimen1 = 5; int dimen2 = len / dimen1; char data[] = new char[len]; char dd[][] = new char[dimen1][dimen2]; for (int i = 0; i < dimen1; i++) { for (int j = 0; j < dimen2; j++) { dd[i][j] = (char) ('a' + i); data[i * dimen2 + j] = (char) ('a' + i); } }
为了能够得到一个比较好的结果,统计十次:
for (int k = 0; k < 10; k++) { CountDownLatch cl = new CountDownLatch(dd.length); long start = System.currentTimeMillis(); for (int i = 0; i < dd.length; i++) { new Thread(new RwThread(new RandomAccessFile(f, "rws"), i * dimen2*2, i * dimen2*2 + dimen2*2, dd[i], cl)).start(); } cl.await(); System.out.println("duration: " + (System.currentTimeMillis() - start)); }
多线程谢文件的代码如下:
import java.io.RandomAccessFile;import java.util.concurrent.CountDownLatch;public static class RwThread implements Runnable { private RandomAccessFile raf; private int start; private int end; private char[] data; private CountDownLatch latch; public RwThread(RandomAccessFile raf, int start, int end, char[] data, CountDownLatch cl) { this.raf = raf; this.start = start; this.end = end; this.data = data; latch = cl; } @Override public void run() { try { raf.seek(start); for (int i = 0; i < data.length; i++) { raf.writeChar(data[i]); } } catch (Exception e) { } finally { try { if (raf != null) { raf.close(); raf = null; } } catch (Exception e) { } } latch.countDown(); }}
得到耗时输出结果如下:
duration: 130duration: 114duration: 115duration: 127duration: 124duration: 117duration: 114duration: 119duration: 118duration: 119首先,看到这个结果我就惊呆了 , 写 500 个字符 尽然花费了 100多 ms ........
那他和单线程操作的差距有多大呢? 请继续往下看:
同样统计十次,代码如下:
for (int k = 0; k < 10; k++) { CountDownLatch cl = new CountDownLatch(1); long start = System.currentTimeMillis(); new Thread(new RwThread(new RandomAccessFile(f, "rw"), 0, len * 2, data, cl)).start(); cl.await(); System.out.println("duration: " + (System.currentTimeMillis() - start)); }
得到耗时输出结果:
duration: 5duration: 2duration: 3duration: 2duration: 3duration: 2duration: 2duration: 2duration: 2duration: 2
天啦,结果居然相差了几十倍呢
今天的内容就到这里了,下面是完整的代码 ......
import java.io.File;import java.io.RandomAccessFile;import java.util.concurrent.CountDownLatch;/** * @author edwin * */public class CreateTmpFile { public static void main(String[] args) throws Exception { String root = "F:" + File.separator + "tmpLog"; File f = new File(root, "ttt.txt"); File ddd = new File(root, "ttt1.txt"); if (!f.exists()) { f.createNewFile(); } if (!ddd.exists()) { ddd.createNewFile(); } System.out.println(f.getAbsolutePath()); int len = 500; int dimen1 = 5; int dimen2 = len / dimen1; char data[] = new char[len]; char dd[][] = new char[dimen1][dimen2]; for (int i = 0; i < dimen1; i++) { for (int j = 0; j < dimen2; j++) { dd[i][j] = (char) ('a' + i); data[i * dimen2 + j] = (char) ('a' + i); } } for (int k = 0; k < 10; k++) { CountDownLatch cl = new CountDownLatch(1); long start = System.currentTimeMillis(); new Thread(new RwThread(new RandomAccessFile(f, "rw"), 0, len * 2, data, cl)).start(); cl.await(); System.out.println("duration: " + (System.currentTimeMillis() - start)); } // for (int k = 0; k < 10; k++) { // CountDownLatch cl = new CountDownLatch(dd.length); // long start = System.currentTimeMillis(); // for (int i = 0; i < dd.length; i++) { // new Thread(new RwThread(new RandomAccessFile(f, "rws"), // i * dimen2*2, i * dimen2*2 + dimen2*2, dd[i], cl)).start(); // } // cl.await(); // System.out.println("duration: " // + (System.currentTimeMillis() - start)); // } } public static class RwThread implements Runnable { private RandomAccessFile raf; private int start; private int end; private char[] data; private CountDownLatch latch; public RwThread(RandomAccessFile raf, int start, int end, char[] data, CountDownLatch cl) { this.raf = raf; this.start = start; this.end = end; this.data = data; latch = cl; } @Override public void run() { try { raf.seek(start); for (int i = 0; i < data.length; i++) { raf.writeChar(data[i]); } } catch (Exception e) { } finally { try { if (raf != null) { raf.close(); raf = null; } } catch (Exception e) { } } latch.countDown(); } }}
0 0
- 多线程那些糟糕的代码——你这样干过吗?
- 《菜鸟、不合格WEB程序员的定界线》之一:你在用这样糟糕的标签切换代码吗?
- 那些年干过的事(二)—成绩查询网站爆库及防护
- 那些年干过的事(三)—系统序列号破解与防护
- 那些年干过的事(五)—无源码程序反编译修改文字
- 那些年干过的事(六)—无源码修改版本号
- 我见过的最糟糕的代码
- 你见过这样的计算器吗?
- 你见过这样的婚礼吗?
- 你做过这样的事情吗?
- 那些年干过的事(一)——php电商网站入侵及防护
- 那些年干过的事(序)
- 死缠烂打追女孩,你见过这样的吗?
- 在DELPHI中你遇到过这样的问题吗?
- 你见过这样强的机器人吗
- 你见过这样的路由表吗?
- 你遇到过这样的问题吗?(string)
- 你见过这样的单例模式吗
- comet反向ajax
- hdu1207汉诺塔II
- Android Studio 中 Gradle 的使用方法及gradle介绍
- 你的flume-ng的第一篇博客
- 常用类String常用的方法
- 多线程那些糟糕的代码——你这样干过吗?
- Java编写的C语言词法分析器
- 自定义异常
- Windows下Sublime Text 默认打开方式问题解决办法
- 递归的应用
- codeforces34D--Road Map
- R.net简介(原创翻译)
- 借助图像直方图来检测特定物(MeanShift、CamShift算法) 很详细
- LA 3207 合作网络 (加权并查集)