您的位置:首页 > 编程语言 > Java开发

Java并发编程总结(一)

2016-06-24 00:00 483 查看
摘要: 本文将总结性的介绍Java并发编程核心方法和框架

首先纠正众多朋友的一个错误,线程同步机制并不是只有synchronized关键字才能实现。还可以有Semaphore、Lock及其实现类ReentrantLock

多线程中线程的同步概念其实是排着队去执行一个任务,执行任务时一个一个执行,并不能并行执行,这样的有点是有助于程序逻辑的正确性,不会出现非线程安全安全问题,保证软件系统功能上的运行稳定性。

1、Semaphore,此类的主要作用是限制线程并发的数量,如果不限制线程并发数量,则CPU的资源就很快耗尽,每个线程执行任务是相当缓慢的,因为CPU要把时间片分配给不同的线程对象,而且上下文切换也要耗费时间,最终造成系统运行效率大幅减低,所以限制线程并发很有必要。Semaphore类发放许可的计算方式是减法操作。构造参数permits是许可的意思,代表同一时间内,最多允许多少个线程同时执行acquire()和release()之间的代码。无参数方法acquire()的作用是使用1个许可,是减法操作。Semaphore类的方法示意图



2、Exchanger,类Exchanger作用是可以使两个线程之间传输数据。比wait/notify要更加方便。Exchanger类的作用与结构相当简单,主要学习就是exchange()方法。类Exchanger中的exchange()方法具有阻塞的特色,也就是此方法别调用后等待其他线程来取得数据,如果没有其他线程取得数据,则一直阻塞等待。



3、CountDownLatch,同步功能辅助类,使用效果是给定一个计数,当使用这个CountDownLatch类的线程判断计数不为0时,则呈await()和countDown()方法来进行。实现等待与继续运行的效果分别需要使用await()和countDown()方法来执行。调用await()方法时判断计数是否为0,如果不为0,则呈等待状态,其他线程调用countDown()方法将计数减1,当计数减到0时,呈等待的线程继续运行。getCount()是获取当前的计数个数。。要说明的是,计数无法被重置,如果需要重置计数,请考虑使用CyclicBarrier类。

4、CyclicBarrier不仅有CountDownLatch所具有的功能,还可以实现屏障等待的功能,也就是阶段性同步,它在使用上的意义在于可以循环实现线程要一起做任务的目标,不是像CountDownLatch一样,仅仅支持一次线程与同步点阻塞的特性。它允许一组线程相互等待,直到达到某个公共屏障点,这些线程必须实时相互等待。方法reset()的作用是重置屏障。

代码示例

[code=language-java]package org.jf.biz;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierTest {
/**
* 创建内部类,实现线程
* */
class MyThread extends Thread{
private CyclicBarrier cbRef;

public MyThread(CyclicBarrier cbRef) {
super();
this.cbRef = cbRef;
}

@Override
public void run() {
try {
Thread.sleep((int) Math.random() * 1000);
System.out.println(Thread.currentThread().getName() + "到了,到达时间:" +System.currentTimeMillis());
cbRef.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
public static void main(String[] args) {
// TODO 这段代码的作用是设置最大为5个的parties同行者,
//也就是说5个线程都执行了cbRef对象的await()方法后程序才继续向下进行
CyclicBarrier cbRef = new CyclicBarrier(5, new Runnable() {

@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("全都到齐了,进行下一步动作");
}
});
CyclicBarrierTest.MyThread[] threadArray = new MyThread[5];
for (int i = 0; i < threadArray.length; i++) {
CyclicBarrierTest test = new CyclicBarrierTest();
CyclicBarrierTest.MyThread thread = test.new MyThread(cbRef);
threadArray[i] = thread;
}
for (MyThread myThread : threadArray) {
myThread.start();
}
}

}

5、Phaser类,CyclicBarrier类本身还有一些缺陷,比如不可动态添加parties计数,调用一次await()方法仅仅占用1个parties计数,所以在JDK7中新增了一个名为Phaser的类来解决这样的问题。Phaser类提供了动态增加parties计数,这点比CyclicBarrier类操作parties更加方便,通过若干个方法来控制多个线程之间同步运行的效果,还可以实现针对某一个线程取消同步运行的效果,而且支持在指定屏障处等待,在等待时还支持中断和非中断等功能。使用Java并发类对线程进行分组同步控制时,Phaser比CyclicBarrier类功能更加强大。Phaser类的方法示意图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息