工作中遇到的问题,记录下解决的思路

问题:

   对磁盘进行碎片化测试(比如说,磁盘空间是16G),从64K开始写文件,写满后删除一半,然后写32K 的数据,写满后删除一半。。。直到4K写满删除一般算是结束

第一阶段:

  使用单独的一个线程进行操作,先写数据,然后删除数据,用循环控制跳出

代码

public class Task extends Thread{
public void run() {
int size = 64;
while(size >=4){
write(size);
delete();
size /= 2;
}
} private void write(int size){
//省略具体的写数据方法,判断是否写满
} private void delete(){
//省略删除的方法
}
}

上述的代码已经实现了功能,但是如果空间很大,怎么半?一个线程写的也太慢了,如何提高效率,写入的速度?

办法就是使用多线程,多个线程同时写,肯定能提升不小的效率

第二阶段:

  使用多个线程进行操作,代码和第一阶段的代码没有变化,共同写同一个磁盘就行

然后出现了新的问题,多线程操作,到最后肯定会出现剩余的磁盘空间就够一个线程使用(假如是线程A ),其他线程已经写完了该阶段的内容(假如是线程B,C,D),开始执行删除操作了,此时,这4个线程有的在写入数据,有的在删除数据,会导致线程A一直读到有剩余空间可以写入(因为其他线程在删除文件,腾出新的空间),这样到最后4K的时候,就出现了A 线程还在写,其他的线程都已经停止好久了。又浪费了好多时间。

  如何解决呢?我想到了使用线程的同步,A线程写完了就等其他线程,等到所有的线程都写完了,大家一起开始删除,等到大家都删除完成了,再一起开始下一个阶段的写入

  那该如何等待呢?

  我用了Object类的wait()和notifyAll()方法。

第三阶段:

  使用同步解决其他线程结束,就剩余一个线程写的问题,进一步的提高效率

代码

import java.util.HashMap;
import java.util.Map; /**
* 状态信息类
*/
public class Status {
private int finishCount = 0;
private int threadCount = 0;
// 存储每个线程的状态
private Map<Integer, Boolean> maps; public Status(int threadCount) {
this.maps = new HashMap<Integer, Boolean>();
this.threadCount = threadCount;
} //更新当前线程是否在等待状态,status = true表示已经在等待了
public synchronized void setStatus(int threadIndex, boolean statu) {
maps.put(threadIndex, statu);
} public boolean getStatus() {
boolean result = true;
for (Map.Entry<Integer, Boolean> entry : maps.entrySet()) {
result = result && entry.getValue();
}
return result;
} // 更新已经完成的线程个数(全部各个阶段执行完调用)
public synchronized void updateFinishCount() {
this.finishCount += 1;
} public int getFinishCount() {
return finishCount;
}
}
/**
* 观察线程
*/
public class Watcher extends Thread{ private int threadCount = 0;
private Status status; public Watcher(Status status,int threadCount ) {
this.status = status;
this.threadCount = threadCount;
} public void run() {
while(true){
//检查是否所有status对象上的线程是否都在等待
if(status.getStatus()){
status.notifyAll();
}
//检查是否所有线程全部执行完成
if(status.getFinishCount() == threadCount){
break;
}
}
}
}
/**
* 具体执行任务的线程
*/
public class Task extends Thread{
private Status status;
private int index;
public Task(Status status,int index) {
this.status = status;
this.index =index;
}
public void run() {
int size = 64;
while(size >=4){
write(size);
synchronized (status) {
status.setStatus(index, true);//设置为等待状态
try {
status.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
status.setStatus(index, false);//取消等待状态
delete();
synchronized (status) {
status.setStatus(index, true);//设置为等待状态
try {
status.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
status.setStatus(index, false);//取消等待状态
size /= 2;
}
} private void write(int size){
//省略具体的写数据方法,判断是否写满
} private void delete(){
//省略删除的方法
}
}

现在看起来是完美了,但是实际的运行过程中,会发现,真的没有控制住线程的同步,还是出现了之前的第二阶段的问题,有一个线程比其他线程慢,而且出现了一个线程没有按照依次递减的顺序执行的古怪情况,我想应该是没有真正的同步造成的。之后又去查找资料,发现Java提供了一个类,就像是为这种情况量身定做的。它就是 CyclicBarrier  ,它自己维护了一个计数器,每当调用一次await()方法,就会阻塞当前的线程,并且计数器减一,计数器的值来源于构造方法,计数器为0的时候,就解除阻塞,更好的是,当计数器为0时,再调用await()方法的时候,会将计数器变成初始值减一,重新开始一个循环。

第四阶段:

  

**
* 具体执行任务的线程
*/
public class Task extends Thread {
private CyclicBarrier cyclicBarrier; public Task(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
} public void run() {
int size = 64;
while (size >= 4) {
write(size);
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
//捕获到该异常的话,表示这个线程不用等待了,需要处理一下,唤醒其他阻塞的线程
e.printStackTrace();
}
delete();
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
size /= 2;
}
} private void write(int size) {
// 省略具体的写数据方法,判断是否写满
} private void delete() {
// 省略删除的方法
}
}

测试的代码

public class Test {
private static final int THREAD_COUNT = 4;
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT);
for(int i=0;i<THREAD_COUNT;i++){
new Task(barrier).start();
}
}
}

  

Java 多线程使用的更多相关文章

  1. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  2. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  3. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  4. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  5. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  6. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  7. java 多线程 1 线程 进程

    Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报  分类: javaSE综合知识点(14)  版权声明:本文为博主原创文章,未经博 ...

  8. 一起阅读《Java多线程编程核心技术》

    目录 第一章 Java多线程技能 (待续...)

  9. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  10. java从基础知识(十)java多线程(下)

    首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...

随机推荐

  1. DP 免费馅饼 HDU1176

    DP 免费馅饼 HDU1176 vjudge题面 一道基本的DP题,状态转移很好想,每一个状态的位置\(pos\)都只能由上一秒的\(pos-1, pos, pos+1\)三个位置转移而来(当然要判断 ...

  2. VS中的DataPager分页

    微软的DataPager分页功能很强大,不要设置数据库存储过程,只要添加个DataPager控件,关联下要分页的控件,简单设置就可以有不错的分页效果.当然要有更理想的效果还是要前台和后台处理下. wi ...

  3. DP Intro - poj 1947 Rebuilding Roads(树形DP)

    版权声明:本文为博主原创文章,未经博主允许不得转载. Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissi ...

  4. c# xml序列化和反序列化。也就是xml的解析和反解析。

    用习惯了newTownSoft.json 的json反序列化.碰到xml是真的不习惯. 每次json反序列化都是直接把json丢到bejson网站生成一个实体类,稍微修改修改一点点变量名.然后直接ne ...

  5. JAVA学习1:Maven3环境搭建

    好长时间不用Java,今天看了下,Maven集成成主流了,在技术水平与日俱进的同时,感叹下IT行业必须有活到老学到老的精神. 先说下环境: Maven:Maven 3.0.5 解压后路径:F:\Mav ...

  6. Junit参数化

    数据驱动测试:测试代码要与测试数据分离 哎~~学习时发现一个问题,写完了测试文件,右击文件时没有run as ->junit test的选项,找了好半天,终于知道了原因,是方法前没有加stati ...

  7. lucene关于IndexReader总结

    IndexReader.使用过程中有时会出现document被删除,reader还是原来的reader没有改变,所以使用openifchanged保证, 又因为IndexReader 初始化很耗费资源 ...

  8. JS原型与原型链图解

  9. 深入理解JavaScript系列(38):设计模式之职责链模式

    介绍 职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象 ...

  10. wcf 登录认证 angular 认证重定向

    自定义认证管理器,分为两级:1.登陆认证.2.权限认证.权限主要是用户.角色.角色用户关系.功能(系统资源).角色功能关系,5部分决定用户的权限(视图). 两层认证都通过后,更新session的最新交 ...