java 多线程有用吗_Java 多线程使用

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

问题:

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

第一阶段:

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

代码

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public class Task extendsThread{public voidrun() {int size = 64;while(size >=4){

write(size);

delete();

size/= 2;

}

}private void write(intsize){//省略具体的写数据方法,判断是否写满

}private voiddelete(){//省略删除的方法

}

}

View Code

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

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

第二阶段:

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

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

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

那该如何等待呢?

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

第三阶段:

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

代码

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

importjava.util.HashMap;importjava.util.Map;/*** 状态信息类*/

public classStatus {private int finishCount = 0;private int threadCount = 0;//存储每个线程的状态

private Mapmaps;public Status(intthreadCount) {this.maps = new HashMap();this.threadCount =threadCount;

}//更新当前线程是否在等待状态,status = true表示已经在等待了

public synchronized void setStatus(int threadIndex, booleanstatu) {

maps.put(threadIndex, statu);

}public booleangetStatus() {boolean result = true;for (Map.Entryentry : maps.entrySet()) {

result= result &&entry.getValue();

}returnresult;

}//更新已经完成的线程个数(全部各个阶段执行完调用)

public synchronized voidupdateFinishCount() {this.finishCount += 1;

}public intgetFinishCount() {returnfinishCount;

}

}

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 观察线程*/

public class Watcher extendsThread{private int threadCount = 0;privateStatus status;public Watcher(Status status,intthreadCount ) {this.status =status;this.threadCount =threadCount;

}public voidrun() {while(true){//检查是否所有status对象上的线程是否都在等待

if(status.getStatus()){

status.notifyAll();

}//检查是否所有线程全部执行完成

if(status.getFinishCount() ==threadCount){break;

}

}

}

}

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** 具体执行任务的线程*/

public class Task extendsThread{privateStatus status;private intindex;public Task(Status status,intindex) {this.status =status;this.index =index;

}public voidrun() {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(intsize){//省略具体的写数据方法,判断是否写满

}private voiddelete(){//省略删除的方法

}

}

View Code

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

第四阶段:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

**

*具体执行任务的线程*/

public class Task extendsThread {privateCyclicBarrier cyclicBarrier;publicTask(CyclicBarrier cyclicBarrier) {this.cyclicBarrier =cyclicBarrier;

}public voidrun() {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(intsize) {//省略具体的写数据方法,判断是否写满

}private voiddelete() {//省略删除的方法

}

}

View Code

测试的代码

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classTest {private static final int THREAD_COUNT = 4;public static voidmain(String[] args) {

CyclicBarrier barrier= newCyclicBarrier(THREAD_COUNT);for(int i=0;i

}

}

}

View Code

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值