CyclicBarrier详解

在上一篇的文章中有提到过 CountDownLatch ,其实 CyclicBarrier 也有异曲同工之妙,不过 CyclicBarrier 是等到所有的线程都到达一个点以后,然后再一起执行

有点像小时候一起去春游,必须等到所有的同学都到了学校,才能一起去坐车,不然就会一直等待。

构造函数

CyclicBarrier 的构造函数有两个,分别如下:

1
2
3
public CyclicBarrier(int parties) {
this(parties, null);
}
阅读更多

Java中多线程使用经验

在子线程中获取父线程的ThreadLocal

如果想子线程想使用父线程的 ThreadLocal,那么父线程中的 inheritableThreadLocals 有值,这样子线程中的 init 方法就会自动的将父线程的 inheritableThreadLocals 设置为 ThreadLocal

但是因为子线程是在 init 方法中进行赋值的,所以如果子线程是由线程池创建的,那么该方法就又可能会失效,当线程池刚初始化完毕的时候,此时线程池中的还没有线程,当调用 execute 方法,此时就会 new 一个线程,那么这时候子线程是可以读取到父线程中 inheritableThreadLocals 的值

但是线程池中的线程是可以被复用的,所以后续如果线程不再创建的时候,那么子线程便不能再次获取父线程中的 inheritableThreadLocals,也就无法再将 ThreadLocal 进行父子线程的传递

如何感知到子线程的异常

阅读更多

浅谈 synchronized 和 volatile

一、锁

从细节上来说,锁分为 乐观锁、悲观锁

乐观锁适用于读多写少的场景,一般是通过 CAS 进行操作,因为不用加锁,所以性能上比悲观锁优秀太多

悲观锁适用于写多读少的场景,性能开销比较大。

1:乐观锁

阅读更多

关于Java线程的一些思考

消费者和生产者的模型:

今天在看《现代操作系统》P73页的一个关于多线程的竞态条件的时候书中说到了唤醒等待位方法,这个方法使我突然想起联想到以前在Java多线程中sleep()方法会清除中断状态的一些类似之处:
树上的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#definde N 100
int count =0;
void producer(void){
int item;
while(True){
item=producer_item();
if (count == N) sleep();
insert_item(item);
count=count+1;
if (count == 1 )wakeup(consumer);
}
}

void consumer(void){
int item;
while(true){
if (count == 0)sleep();
item =remove_item();
count=count -1;
if (count == N-1) wakeup(producer);
consumer_item()
}
}

在书中提到过一个情况就是:当消费者判断count==0的时候是会睡眠的,但是此时由于某种情况(线程的sleep()方法还没被执行完),而恰巧生产者又生产了一个item,导致此时count加一为1,而当count为1的时候生产者是会发出一个wakeup信号给消费者的,此时,由于消费者并没有睡眠因此会忽略掉该信号,而当消费者真正睡眠之后又由于生产者再不会进行通知,导致队列被生产者塞满,从而该模型阻塞。
那么为了解决该方法,书中引入了唤醒等待位方法,该方法就是在生产者发出信号给消费者的时候添加一个中断状态,而当该线程需要进行睡眠的时候会先判断状态,若是wakeup则不进行睡眠

Java多线程中的引用:

阅读更多