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