JUC主要说的是一下几个类 ReentrantLock,CountDownLatch,CyclicBarrier,Phaser,ReadWriteLock,Semaphore,Exchanger.
ReentrantLock和synchronized
synchronized是可重入锁,在线程加锁的过程中锁的对象不能发生变化,例如锁对象是当前对象的一个属性,在线程运行的时候,不能把锁对象进行改变。
当一个synchronized的方法m1调用synchronized的方法m2,根据可重入锁的原则,这两个锁的对象是一个。(m1和m2这两个方法在同一个类或者是子类继承父类)
如果要单独开启两个线程,分别运行这两个方法,比如说先运行的m1方法,如果在想单独启动调用m2方法的进程,m2的线程无法执行,必须要等到m1方法将锁释放才能运行。如果要想运行m2方法可以在m1方法中调用m2。
对于这种情况,可以使用ReentrantLock替代synchronized,是的是lock()方法和unlock()方法,
这样就可以单独启动进程了。
另外ReentrantLock类中还有一个方法是tryLock进行尝试锁定,不管锁定与否,方法都将继续执行。synchronized如果搞不定的话他肯定就阻塞了,但是ReentrantLock是自己就可以决定你到底要不要wait。
还有lockInterrupuibly()这个方法,对interrupt()方法做出响应,可以被打断的加锁,如果以这种方式加锁的话我们可以调用一个t2.interrupt()打断线程2的等待。线程1上来之后加锁,加锁之后开始睡,睡的没完没了的,被线程1拿到这把锁的话,线程2如果说再想拿到这把锁不太可能,拿不到锁他就会等待,如果我们使用原来的这种lock()是打断不了他的,那么我们就可以用另外一中方式lockInterruptibly()这个方法打断的,当你想要停止线程2就可以使用interrupt()。
CountDownLatch和join
new了100个线程,接下来,又来了100个数量的CountDownLatch,就是一个门栓,门栓上记了个数100,每一个线程结束的时候让latch.countDown(),然后所有线程start(),再latch.await()。最后结束。那么CountDown的作用要看latch.await(),他的意思就是说给我看住门。给我插住不要动,每个线程执行下countDown,countDown在原来的基础上减一,一直到这个数字变成0的时候门栓就会被打开,这就是他的概念,他是用来等待线程结束的。
用join实际上不太好控制,必须要你线程结束了才能控制,但是如果是一个门栓的话我再线程里不停的countDown,在一个线程里就可以控制这个门栓什么时候往前走,用join我只能是当前线程结束了你才能自动往前走,当然join可以,但是countDown更灵活。
join 等待该线程终止。在主线程调用一个t1线程,在主线程中t1.join这个时候,主线程会停止,等待t1线程执行,只有t1线程执行完,主线程在继续执行。
CyclicBarrier
这个单词的意思是循环栅栏,相当于水库的一个阀门,这个阀门关闭这就是开始往里面注水,什么时候水到警戒水位了,开始打开阀门放水,水放完之后,再把阀门关闭,在放水,水满再放。
Phaser
Phaser是按照不同的阶段来对进行执行,就是它本身是维护这一个阶段这样的一个成员变量,当前执行到哪个阶段,是第0个阶段,还是第1个阶段等等,每个阶段不同的时候这个线程都可以往前走,有的线程走到某个阶段就停了,有的线程一直会走到结束。如果程序分好几个阶段执行,而且有的必须的几个一起参与情况下可以使用。
例如车辆生产,可以分成好几个阶段,装车轮子,装发动机等等。这几个阶段可以分开执行。最后组装成车。
ReadWriteLock
读写锁,分成两部分看,读可以理解为共享锁,意思就是读的时候每个进程都可以读到,写可以理解为排他锁,就是在写的时候,只有这此一条线程进行写,其它线程的读和写都不能进行操作。
Semaphone
这个是限流锁,例如 有一个4车道的高速,这里只有一个收费站,这只能有一个车辆可以通行。限制了车的流量。
Exchanger
交换,这个锁只能对两个进程进行操作,线程1和线程2进行交换,将两个线程之间互相交换数据。