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

JAVA 多线程编程之一(基础)

2013-09-05 18:02 411 查看
1.原子变量(java.util.concurrent.atomic)

  原子状态,变化不会被打断,如 AtomicLong , AtomicInteger

2.内部锁 synchronized 块

  synchronized方法的锁就是方法所在的对象本身,可重入

3.共享变量

  Volatile变量,每次从内存取出数据,可以获得最新的副本。

  没有同步情况下的共享变量,可能执行顺序不是按照代码的组织,

  

public  class NoVisibility{
private static boolean ready;
private static int number;

private static class ReaderThread extends Thread{
public void run(){
while(!ready){
Thread.yield();
}
System.out.println(number);
}
}

public static void main(String args[]){
new ReaderThread().start();
number = 42;
ready =  true;
}


  栈限制,把本地的引用类型限制在本地线程中,不溢出

  不可变对象永远是线程安全的

4.ThreadLocal 允许线程和自己的变量保存在一起

  向已有的线程安全类添加功能,

  

public class BetterVector<E> extends Vector<E>{
public synchronized boolean putIfAbsent(E x){
...
}
}


但是下面这种方式不是线程安全的:

public class ListHelper<E>{
public List<E> list = Collections.synchronizedList(new ArrayList<E>());

public synchronized boolean putIfAbsent(E x){
...
}
}


因为synchronized关键字锁住的是 ListHelpder类,所以并没有获得List的锁,那么在putIfAbsent中修改List时,是不能保证

其它方法不对list修改。

下面的方法才是正确的:

public class ListHelper<E>{
public List<E> list = Collections.synchronizedList(new ArrayList<E>());

public  boolean putIfAbsent(E x){
synchronized(list);
...
}
}


或者是使用组合实现List接口,这样第一种方式就是正确的,因为获得了正确的锁。

5. 同步容器

Java 5.0 提供了并发容器来替换同步容器,提高并发的效率。 ConcurrentHashMap代替SynchronizedMap

FutureTask 通过Callable 实现,可以理解为是一个可携带结果的Runnable

semaphore 信号量,控制对资源的访问数量限制

Barrier 提供一种可以一次执行多个线程,直到所有的线程都完成才继续进行,有任何一个线程没有完成,所有

完成的现成都要等待这个线程完成

一个正确的多线程访问的缓存的写法

package net.jcip.examples;

import java.util.concurrent.*;

/**
* Memoizer
* <p/>
* Final implementation of Memoizer
*
* @author Brian Goetz and Tim Peierls
*/
public class Memoizer <A, V> implements Computable<A, V> {
private final ConcurrentMap<A, Future<V>> cache
= new ConcurrentHashMap<A, Future<V>>();
private final Computable<A, V> c;

public Memoizer(Computable<A, V> c) {
this.c = c;
}

public V compute(final A arg) throws InterruptedException {
while (true) {
Future<V> f = cache.get(arg);
if (f == null) {
Callable<V> eval = new Callable<V>() {
public V call() throws InterruptedException {
return c.compute(arg);
}
};
FutureTask<V> ft = new FutureTask<V>(eval);
f = cache.putIfAbsent(arg, ft);
if (f == null) {
f = ft;
ft.run();
}
}
try {
return f.get();
} catch (CancellationException e) {
cache.remove(arg, f);
} catch (ExecutionException e) {
throw LaunderThrowable.launderThrowable(e.getCause());
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: