例示FutureTask + Thread

package player.kent.chen.learn.future; import java.io.File; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; import org.apache.commons.io.FileUtils; public class HelloFutureTask { public static void main(String[] args) { //一个待完成事项 Callable<String> callable = new Callable<String>() { public String call() throws Exception { return FileUtils.readFileToString(new File("/home/kent/temp/1.txt")); } }; //生成FutureTask对象 FutureTask<String> task = new FutureTask<String>(callable) { @Override //重载这个方法,可以在任务执行完时干点事 protected void done() { super.done(); System.out.println("The task is …

例示FutureTask + Thread Read More »

例示Executor + Callable + Future的使用

package player.kent.chen.learn.future; import java.io.File; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; public class HelloFuture { public static void main(String[] args) throws Throwable { //一个待完成事项 Callable<String> task = new Callable<String>() { public String call() throws Exception { return FileUtils.readFileToString(new File("/home/kent/temp/1.txt")); } }; //生成executor并异步执行 ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> future …

例示Executor + Callable + Future的使用 Read More »

ConcurrentHashMap的弱一致性

ConcurrentHashMap提供的迭代器不会抛出ConcurentModificationException,也就是说迭代器如果发现数据被修改了,它会尽量去访问到对Map已做的修改,但这个不能保证。 所以它读到的可能是过期的数据,也就是存在“弱一致性”问题。 对于一个被 并发访问的ConcurrentHashMap来说,size()和isEmpty()往往是不准确的。 但不要误会,以为ConcurrentHashMap的一致性很弱;除了迭代、size()、isEmpty()等操作有这个问题之外,像remove(), put()操作等都比HashMap提供了更高的一致性,因为这些操作都是原子操作。 这些操作中使用了粒度比较细的锁,不会像HashTable一样锁住整个容器,但也不至于像HashMap那样完全不加锁。

理解ConcurrentModificationException

当一个线程对类集进行迭代时,如果另一个线程修改了类集,迭代线程会发现这个修改,然后就会抛出ConcurrentModificationException . 不过即使出现了上面所说的并发读写,java类集也不能100%保证会抛出ConcurrentModificationException.  因为迭代线程在执行“判断类集是否修改 + 若有则抛出异常”这两步的组合时并没有加锁。 很有可能在 “发现类集没有修改后”, 另一个线程把类集修改了。 另一个要注意的是很多非迭代操作都可能引发ConcurrentModificationException, 因为这些操作隐式地调用了迭代。 比如 类集的hashCode(),equals(), containsAll()等,就连toString()都会,所以,在日志里直接打印类集时,要小心。

ReadWriteLock代码示例

ReadWriteLock的契约是:    1. 读、写都要先获得相应的锁    2. 如果在共享数据上已经加了读锁,则其他线程可以继续加读锁,再不能加写锁;也就是说,你读时别人也可以读,但不能写    3. 如果已经加了写锁,则其他线程不能加任何锁;也就是说,你在写时别人不能写也不能读 可见ReadWriteLock适用于读多写少的情形。 下面的代码例子是从《JAVA并发编程实践》中抄来的。注意我们一般用可重入的ReadWriteLock,即ReentrantReadWriteLock

例示CountDownLatch的使用

CountDownLatch可用于一个线程等待另外一些线程做了一些事后再做自己的事。做事的线程做完事后报一下数:将一个初数值减1,等这个数值变成0时,等待的线程就可以做自己的事。 用join()也能完成相同的目标。但join()意味着必须等待做事线程终止自己才能动手,CountDownLatch没有这个限制,做事线程再报完数后还可以继续做自己的事。 执行结果: 我是乞丐,要钱吃饭 walker0 已经动身了 walker1 已经动身了 walker2 已经动身了 我是行人walker0  我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱 我是行人walker1  我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱 我是行人walker2  我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱 我是乞丐,钱要够了,现在去买吃的 我是行人walker0  给完钱后,我在无边的人海中继续前行直到永远。。。 我是行人walker1  给完钱后,我在无边的人海中继续前行直到永远。。。 我是行人walker2  给完钱后,我在无边的人海中继续前行直到永远。。。 同时各行人线程仍处于alive状态。

例示CyclicBarrier的使用

package player.kent.chen.learn.barrier; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class HelloBarrier { /** * 大家都到齐后,再一起开火 */ private static final class FireTogether implements Runnable { private CyclicBarrier barrier; public FireTogether(CyclicBarrier barrier) { super(); this.barrier = barrier; } public void run() { try { barrier.await(); //等别的线程到达集合点 System.out.println(Thread.currentThread().getName() + ": 哥开火了!"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (BrokenBarrierException …

例示CyclicBarrier的使用 Read More »

理解Java Interruption机制

本文内容基本源自 Java theory and practice: Dealing with InterruptedException Interruption机制是干什么用的? Interruption用于一个线程“礼貌地”打断另一个线程,被打断的线程可以理会,也可以不理会。(interruption is a way of politely asking another thread to stop what it is doing if it wants to, at its convenience. ) 不过后面可以看到,不理会者,不是好人(a good citizen) 具体怎么interrupt ? 1. 打断者执行thread.interrupt() 2. 被打断者要么收到InterruptedException, 要么会发现自己的isInterrupted() == true. 注意:    1. 如果被打断者在interruption来临时正在执行sleep(), I/O读写等Blocking Method, 则会收到InterruptedException(所以这些方法一般会throws InterruptedException)    2. 如果被打断者没有执行上述Blocking …

理解Java Interruption机制 Read More »

Java Semaphore例子

package player.kent.chen.learn.semaphore; import java.util.concurrent.Semaphore; public class HelloSemaphore { private static final class Room { //信号量作为共享资源的属性 private Semaphore semaPhore = new Semaphore(3, true); //每次只允许3个人在房内 public void take() throws InterruptedException { try { semaPhore.acquire(); System.out.println(Thread.currentThread().getName() + " is now in the room"); Thread.sleep(3000); } finally { semaPhore.release(); } } } private static final class Guest implements Runnable …

Java Semaphore例子 Read More »

CAS操作中的ABA问题及Java中的解决办法

一般的CAS在决定是否要修改某个变量时,会判断一下当前值跟旧值是否相等。如果相等,则认为变量未被其他线程修改,可以改。 但是,“相等”并不真的意味着“未被修改”。 另一个线程可能会把变量的值从A改成B,又从B改回成A。 这就是ABA问题。 很多情况下,ABA问题不会影响你的业务逻辑因此可以忽略。但有时不能忽略,这时要解决这个问题,一般的做法是给变量关联一个只能递增、不能递减的版本号。在compare时不但compare变量值,还要再compare一下版本号。 Java里的AtomicStampedReference 类就是干这个的。