1.ReentrantLock的简单使用
Reentrant n.再进入
ReentrantLock 一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。(从jdk1.8中文版复制而来)
可以完成synchronized相同的作用,但必须手动释放锁
package com.dingyu2; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**@author dingyu */
- Reentrant n.再进入
- ReentrantLock 一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和语义,但具有扩展功能。(从jdk1.8中文版复制而来)
- 可以完成synchronized相同的作用,但必须手动释放锁
public class ReentrantLock1 {
private Lock lock = new ReentrantLock();</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { lock.lock();//synchronized(this)类似,锁定的是堆的对象 </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i < 10; i++<span style="color: #000000;">) System.out.println(</span>"m1-" +<span style="color: #000000;"> i); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) { System.out.println(</span>"m1启动"<span style="color: #000000;">); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { System.out.println(</span>"m1结束"<span style="color: #000000;">); lock.unlock(); } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { lock.lock(); </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i < 10; i++<span style="color: #000000;">) System.out.println(</span>"m2-" +<span style="color: #000000;"> i); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) { System.out.println(</span>"m2启动"<span style="color: #000000;">); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { System.out.println(</span>"m2结束"<span style="color: #000000;">); lock.unlock(); } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) { ReentrantLock1 reentrantLock1 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReentrantLock1(); </span><span style="color: #0000ff;">new</span> Thread(() -><span style="color: #000000;"> reentrantLock1.m1()).start(); </span><span style="color: #0000ff;">new</span> Thread(() -><span style="color: #000000;"> reentrantLock1.m2()).start(); }
}
2.ReentrantLock对synchronized的扩展之tryLock()
package com.dingyu2; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**@author dingyu */
- ReentrantLock对synchronized的扩展之tryLock()
public class ReentrantLock2 {
private Lock lock = new ReentrantLock();</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() { lock.lock();</span><span style="color: #008000;">//</span><span style="color: #008000;"> 一直锁着,不手动释放, 和synchronized(this)类似,锁定的是堆的对象</span>
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() { </span><span style="color: #0000ff;">boolean</span> isNotLock = lock.tryLock();<span style="color: #008000;">//</span><span style="color: #008000;"> 如果别的进程锁着就返回false,如果没锁返回true </span><span style="color: #008000;">//</span><span style="color: #008000;"> 我们可以根据有没有锁来执行自己的逻辑,而不需要等着锁的释放,更加灵活</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (isNotLock) { System.out.println(</span>"lock对象没有被锁定"<span style="color: #000000;">); } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> { System.out.println(</span>"lock对象被锁定了"<span style="color: #000000;">); } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) { ReentrantLock2 reentrantLock2 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReentrantLock2(); </span><span style="color: #0000ff;">new</span> Thread(() -><span style="color: #000000;"> reentrantLock2.m1()).start(); </span><span style="color: #0000ff;">new</span> Thread(() -><span style="color: #000000;"> reentrantLock2.m2()).start(); }
}
3.ReentranLock对synchronized的扩展:可以被另外的线程打断
package com.dingyu2; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; /**@author dingyu */
- ReentranLock对synchronized的扩展:可以被另外的线程打断
- 因为m1方法一直占着锁,m2永远不可能得到锁,既然得不到锁,我们就关闭m2好了,这时候得用lockInterruptibly
public class ReentrantLock3 {
private Lock lock = new ReentrantLock();</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() { lock.lock(); </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { System.out.println(</span>"t1 start"<span style="color: #000000;">); </span><span style="color: #0000ff;">while</span> (<span style="color: #0000ff;">true</span><span style="color: #000000;">) { } } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { lock.unlock(); System.out.println(</span>"t1 end"<span style="color: #000000;">); } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { lock.lockInterruptibly(); System.out.println(</span>"t2 start"<span style="color: #000000;">); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) { System.out.println(</span>"t2被打断了"<span style="color: #000000;">); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (lock.tryLock()) lock.unlock(); System.out.println(</span>"t2 end"<span style="color: #000000;">); } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) { ReentrantLock3 reentrantLock3 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReentrantLock3(); Thread t1 </span>= <span style="color: #0000ff;">new</span> Thread(() -> reentrantLock3.m1(), "t1"<span style="color: #000000;">); t1.start(); Thread t2 </span>= <span style="color: #0000ff;">new</span> Thread(() -> reentrantLock3.m2(), "t2"<span style="color: #000000;">); t2.start(); t2.interrupt(); }
}
4.ReentrantLock对synchronized的扩展 : 可以指定公平锁
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /**@author dingyu */
- ReentrantLock对synchronized的扩展 : 可以指定公平锁,哪个线程等待时间长,哪个先执行
- 在构造函数中放入ture参数
public class ReentrantLock4 {
private Lock lock = new ReentrantLock(true);</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() { </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 0; i < 10; i++<span style="color: #000000;">) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { lock.lock(); System.out.println(Thread.currentThread().getName() </span>+ "running"<span style="color: #000000;">); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { lock.unlock(); } } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) { ReentrantLock4 lock4 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReentrantLock4(); </span><span style="color: #0000ff;">new</span> Thread(()->lock4.m1(),"t1"<span style="color: #000000;">).start(); </span><span style="color: #0000ff;">new</span> Thread(()->lock4.m1(),"t2"<span style="color: #000000;">).start(); }
}
5.使用wait和notifyAll实现消费者生产者模式
package com.dingyu2; import java.util.LinkedList; /**@author dingyu */
- 使用wait和notifyAll实现消费者生产者模式
public class ProduceConsumer {
private final LinkedList<Integer> lists = new LinkedList<Integer>();
private final int MAX = 10;
private int count = 0;</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> put(Integer i) { </span><span style="color: #0000ff;">while</span> (lists.size() == MAX) { <span style="color: #008000;">//</span><span style="color: #008000;"> wait大多数情况和while一起用</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">this</span>.wait();<span style="color: #008000;">//</span><span style="color: #008000;"> 如果满了我就释放锁,并且等待</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) { e.printStackTrace(); } } lists.add(i);</span><span style="color: #008000;">//</span><span style="color: #008000;"> 生产一个</span> count++<span style="color: #000000;">; </span><span style="color: #0000ff;">this</span>.notifyAll();<span style="color: #008000;">//</span><span style="color: #008000;"> 叫醒消费者可以消费啦</span>
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> Integer get() { </span><span style="color: #0000ff;">while</span> (lists.size() == 0<span style="color: #000000;">) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">this</span>.wait();<span style="color: #008000;">//</span><span style="color: #008000;"> 如果集合为空,不能消费,释放锁,等着</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) { e.printStackTrace(); } } Integer num </span>=<span style="color: #000000;"> lists.removeFirst(); count</span>--<span style="color: #000000;">; </span><span style="color: #0000ff;">this</span>.notifyAll();<span style="color: #008000;">//</span><span style="color: #008000;"> 叫醒生产者,可以继续生产啦</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> num; }
}
6.使用Condition 完成生产者消费者模式
package com.dingyu2; /** * 使用Condition 完成生产者消费者模式 * @author dingyu * */import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ProduceConsumer2 {
private final LinkedList<Integer> lists = new LinkedList<Integer>();
private final int MAX = 10;
private int count = 0;</span><span style="color: #0000ff;">private</span> Lock lock = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ReentrantLock(); </span><span style="color: #0000ff;">private</span> Condition p = lock.newCondition();<span style="color: #008000;">//</span><span style="color: #008000;"> 生产者</span> <span style="color: #0000ff;">private</span> Condition c = lock.newCondition();<span style="color: #008000;">//</span><span style="color: #008000;"> 消费者</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> put(Integer i) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { lock.lock(); </span><span style="color: #0000ff;">while</span> (lists.size() ==<span style="color: #000000;"> MAX) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { p.await(); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) { e.printStackTrace(); } } lists.add(i); count</span>++<span style="color: #000000;">; c.signalAll(); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { lock.unlock(); } } </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Integer get() { Integer i </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { lock.lock(); </span><span style="color: #0000ff;">while</span> (lists.size() == 0<span style="color: #000000;">) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { c.await(); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) { e.printStackTrace(); } } i </span>=<span style="color: #000000;"> lists.removeFirst(); count</span>++<span style="color: #000000;">; p.signalAll(); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { lock.unlock(); } </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> i; }
}
7.ThreadLocal 线程局部变量 每个线程中的这个变量归自己线程管
package com.dingyu; public class ThreadLocal1 {
private ThreadLocal<Integer> tl = new ThreadLocal<Integer>();</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m1() { System.out.println(tl.get()); } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> m2() { tl.set(</span>7898<span style="color: #000000;">); } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) { ThreadLocal1 local1 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ThreadLocal1(); </span><span style="color: #0000ff;">new</span> Thread(() -><span style="color: #000000;"> local1.m2()).start(); </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { Thread.sleep(</span>5000<span style="color: #000000;">); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (InterruptedException e) { e.printStackTrace(); } </span><span style="color: #0000ff;">new</span> Thread(() -><span style="color: #000000;"> local1.m1()).start(); }
}