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

Java 并发 同步方案总结

2016-03-06 22:04 513 查看

Synchronized关键字:

实现:利用每个对象的内部锁进行同步;
使用1:(下面的await和notifyAll可有可无)
public synchronized void myMethod(){
if(!(ok to process))
await();
//add your code here
notifyAll();
}

使用2:(下面的await和notifyAll可有可无)
Object obj = new Object();
public synchronized void myMethod(){
syschronized(obj){
if(!(ok to process))
obj.await();
//add your code here
obj.notifyAll();
}
}

ReentrantLock类:

使用:
Lock mlock = new ReentrantLock();

public void myMethod(){
mlock.lock();
try{
//add your code here
}
finally{
mlock.unlock();
}
}

注意:
锁是可以重入的,一个线程可以重复的获得已经持有的锁;

ReentrantReadWriteLock类:

适用于很多线程从一个数据结构读取数据而很少的线程修改其中数据;
使用:
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
//该锁可以被多个读操作共用的读锁,但会排斥写操作
Lock readLock = rwl.readLock();
//该锁排斥所有其他的读操作和写操作
Lock writeLock = rwl.writeLock();

public int getNumber(){
readLock.lock();
try{
//add your code here
}
finally{
readLock.unlock();
}
}
public void setNumber(){
writeLock.lock();
try{
//add your code here
}
finally{
writeLock.unlock();
}
}


Condition条件:(与ReentrantLock配套使用)

使用:

Lock mlock = new ReentrantLock();
Condition mCondition = mlock.newCondition();

public void myMethod(){
mlock.lock();
try{
if(!(ok to process))
mConditon.await();
//add your code here
mConditon.signalAll();
}
finally{
mlock.unlock();
}
}

同步器:

Semaphore(信号量):

信号量维持一个计数,许可的数目时固定的,由此限制了通过的线程数量;
线程通过调用acquire请求许可,通过release()释放许可;
许可不是必须由获取它的线程释放,任何线程都可以释放任意数目的许可;

CountDownLatch(倒计时门栓):

让一个线程集等待直到计数器变为0;
倒计时门栓是一次性的,一旦计数为0,就不能再重用了;
调用countDown则计数减1;

CyclicBarrier(障栅):

当指定数目的线程都完成了相应的工作后,到达障栅处,此时障栅自动撤销,线程可以继续运行;
使用1
<pre name="code" class="java">        static int data=0;
static int nthreads = 10;
static CyclicBarrier barrier = new CyclicBarrier(nthreads);
public static void main(String[] args)  {
for(int ii=0;ii<nthreads;ii++){
Runnable myAction = new Runnable(){
public void run(){
//add pre-action
data++;
try {
barrier.await();
System.out.println(data);
//add post-action
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
new Thread(myAction).start();
}

}<span style="font-family: 微软雅黑; widows: auto;">//会打印输出10个10;破栅后会执行执行await后面的代码</span>



使用2:
static int data=0;
static int nthreads = 10;
static Runnable barrierAction = new Runnable(){
@Override
public void run() {
//add post-action
System.out.println(data);
}
};
static CyclicBarrier barrier = new CyclicBarrier(nthreads,barrierAction);
public static void main(String[] args)  {
for(int ii=0;ii<nthreads;ii++){
Runnable myAction = new Runnable(){
public void run(){
//add pre-action
data++;
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
};
new Thread(myAction).start();
}

}//会打印输出1个10<span style="font-family: 微软雅黑; widows: auto;">;破栅后会先执行<span style="widows: auto;">barrierAction的run方法,随后</span>执行await后面的代码</span>


Exchanger(交换器):

两个线程在同一个缓冲区的两个实例上工作;
如一个向缓冲区写,一个从缓冲区读;
当各自完成了各自的工作后交换缓冲区;

SynchronousQueue(同步队列):

实现了BlockingQueue接口
不过它的size永远是0;
调用put方法时将一直阻塞下去,知道另一个线程调用了take方法为止;

Volatile域:

保证读取到的值是当前最新的;用该关键字声明的变量具备可见性;

阻塞队列:

java.util.concurrent包下有如下阻塞队列

LinkedBlockingQueue:容量没上限,也可指定最大容量,是一个双端的版本
ArrayBlockingQueue:构造时需要指定容量
PriorityBlockingQueue:优先级队列
注意:使用put方法添加元素,使用take方法获取元素,这两个方法是阻塞的

线程安全集合:

java.util.concurrent包下

ConcurrentHashMap
ConcurrentSkipListMap
ConcurrentSkipListSet
ConcurrentLinkedQueue
CopyOnWriteArrayList
CopyOnWriteArraySet
Vector
HashTable:key/value均不支持是null
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: