(1)LockSupport
这儿park
和unpark
其实实现了wait
和notify
的功能,不过还是有一些差别的。
park
不需要获取某个对象的锁- 因为中断的时候
park
不会抛出InterruptedException
异常,所以需要在park
之后自行判断中断状态,然后做额外的处理
package dayo4; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; /** * @author: zdc * @date: 2020-03-27 */ public class _1LockSupport { public static void main(String[] args) throws InterruptedException { Thread t = new Thread(()->{ for (int i = 0; i < 10; i++) { System.out.println(i); if(i==5) LockSupport.park(); } }); t.start(); TimeUnit.SECONDS.sleep(2); LockSupport.unpark(t); } }
(2)题目1
实现一个容器,提供两个方法,add,size 写两个线程,线程1添加10个元素到容器中,线程2实现监控元素的个数,当个数到5个时,线程2给出提示并结束
- 1
package dayo4; import java.util.ArrayList; import java.util.List; /** * @author: zdc * @date: 2020-03-27 */ public class MyContainer1<T> { private List<T> list = new ArrayList<>(); public void add(T t) { list.add(t); } public int size() { return list.size(); } public static void main(String[] args) { Object lock = new Object(); MyContainer1<String> container = new MyContainer1<>(); new Thread(() -> { synchronized (lock) { if (container.size() != 5) { try { lock.wait(); //1 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("元素已经加到5"); lock.notify(); } }, "t1").start(); new Thread(() -> { synchronized (lock) { for (int i = 0; i < 10; i++) { container.add("element" + i); if (container.size() == 5) { //注意线程2要wait 这样线程1才会活的执行权 否则只是线程2只是被notify 但并没有获得cpu执行权.wait会释放锁, // notify仅仅只是通知,不释放锁)notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了, // 但不是马上得到锁,因为锁还在别人手里,别人还没释放 lock.notify(); try { lock.wait();//线程1释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(i+1); } } }, "t2").start(); } }
- 2
CountDownLatch
public class MyContainer2<T> { private List<T> list = new ArrayList<>(); public void add(T t) { list.add(t); } public int size() { return list.size(); } public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(1); MyContainer1<String> container = new MyContainer1<>(); new Thread(() -> { if (container.size() != 5) { try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("元素已经加到5"); } , "t1").start(); new Thread(() -> { for (int i = 0; i < 10; i++) { container.add("element" + i); if (container.size() == 5) { countDownLatch.countDown(); try { countDownLatch.await(); //这儿存疑 因为此时N=0了 为什么线程t2会停住一下下呢? } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(i + 1); } }, "t2").start(); } }
- 3
LockSupport
package dayo4; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.LockSupport; /** * @author: zdc * @date: 2020-03-27 */ public class MyContainer2<T> { private List<T> list = new ArrayList<>(); public void add(T t) { list.add(t); } public int size() { return list.size(); } static Thread t2 = null; // public static void main(String[] args) { CountDownLatch countDownLatch = new CountDownLatch(1); MyContainer1<String> container = new MyContainer1<>(); Thread t1 = new Thread(() -> { if (container.size() != 5) { LockSupport.park(); } System.out.println("元素已经加到5"); LockSupport.unpark(t2); } , "t1"); t1.start(); t2 = new Thread(() -> { for (int i = 0; i < 10; i++) { container.add("element" + i); if (container.size() == 5) { LockSupport.unpark(t1); LockSupport.park(); } System.out.println(i + 1); } }, "t2"); t2.start(); } }
(3)题目2
两个线程,分别打印AB,其中线程A打印1,2,3,4,5 B线程打印A,B,C....使之出现A1B2..... 的效果。
- wait notify
public class Demo { public static void main(String[] args) { Character[] characters1 = {'1', '2', '3', '4', '5'}; Character[] characters2 = {'A', 'B', 'C', 'D', 'E'}; Object lock = new Object(); new Thread(() -> { for (int i = 0; i < characters1.length; i++) { synchronized (lock) { System.out.println(characters1[i]); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } lock.notify(); } } }, "t1").start(); new Thread(() -> { for (int i = 0; i < characters2.length; i++) { synchronized (lock){ System.out.println(characters2[i]); lock.notify(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "t2").start(); } }
- 2 ReentrantLock
public class Demo {
public static void main(String[] args) {
Character[] characters1 = {'1', '2', '3', '4', '5'};
Character[] characters2 = {'A', 'B', 'C', 'D', 'E'};
ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
new Thread(() -> {
lock.lock();
for (int i = 0; i < characters1.length; i++) {
System.out.println(characters1[i]);
condition2.signal();
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
condition2.signal(); //循环题结束后t1,t2最后肯定有一个没醒过来的所以要唤醒
lock.unlock();
}, "t1").start();
new Thread(() -> {
lock.lock();
for (int i = 0; i < characters2.length; i++) {
System.out.println(characters2[i]);
condition1.signal();
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
condition1.signal();
lock.unlock();
}, "t2").start();
}
}
(4)题目3
写一个固定容量同步容器,拥有put和get方法,以及getCount方法,能够支持多个生产者和多个消费者线程拥塞调用。
1)使用synchronized锁的notify、notifyAll来实现
生成消费交互
public class MyContainer<T> { private static int count=0; //生产的数 private final List<T> list = new ArrayList<>(); //最大容量 public static final int MAX_CAPACITY = 10; public static final int FIRST= 0; public synchronized void put(T t){ while (list.size()==MAX_CAPACITY){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("生产了"+list.add(t)+":"+t); this.notifyAll(); } public synchronized void remove(){ while (list.size()==0){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("消费了:"+list.remove(FIRST)); this.notifyAll(); } public static void main(String[] args) { MyContainer<String> container = new MyContainer<>(); for (int i = 0; i < 10; i++) { //启动十个消费线程 new Thread(container::remove).start(); //启动20个生产线程 new Thread(()->{ container.put(""+count++); }).start(); } } }
无线生产 消费
public class MyContainer { private static int count = 1; //生产的数 private final List list = new ArrayList<>(); //最大容量 public static final int MAX_CAPACITY = 10; public static final int FIRST = 0; public synchronized void put() { while (true){ while (list.size() == MAX_CAPACITY) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } list.add(count++); System.out.println("线程" + Thread.currentThread().getName() + "生产了" + ":" + count); this.notifyAll(); } } public synchronized void remove() { while (true){ while (list.size() == 0) { try { System.out.println("等待生产"); this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("消费了:" + list.remove(FIRST)); this.notifyAll(); } } public static void main(String[] args) { MyContainer container = new MyContainer(); for (int i = 0; i < 10; i++) { //启动5个消费线程 new Thread(container::remove, i + "").start(); //启动20个生产线程 new Thread(() -> { container.put(); }, i + "").start(); } } }
2)使用ReentrantLock锁的notify、notifyAll来实现
public class _MyContainer2{ private static int count = 1; //生产的数 private final List list = new ArrayList<>(); //最大容量 public static final int MAX_CAPACITY = 10; public static final int FIRST = 0; private final Lock lock = new ReentrantLock(); private final Condition consumer= lock.newCondition(); private final Condition producer= lock.newCondition(); public void put() { while (true) { lock.lock(); while (list.size() == MAX_CAPACITY) { try { producer.await(); } catch (InterruptedException e) { e.printStackTrace(); } } list.add(count++); System.out.println("线程" + Thread.currentThread().getName() + "生产了" + ":" + count); consumer.signalAll(); } } public void remove() { while (true) { lock.lock(); while (list.size() == 0) { try { consumer.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("消费了:" + list.remove(FIRST)); producer.signalAll(); } } public static void main(String[] args) { _MyContainer1 container = new _MyContainer1(); for (int i = 0; i < 1; i++) { //启动5个消费线程 new Thread(container::remove, i + "").start(); //启动20个生产线程 new Thread(() -> { container.put(); }, i + "").start(); } } }
3)直接使用BlockingQueue实现
package dayo4; import java.util.ArrayList; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; /** * @author: zdc * @date: 2020-03-30 */ public class _MyContainer3 { private static int count = 1; //生产的数 public static final int MAX_CAPACITY = 10; public static final int FIRST = 0; private BlockingQueue queue = new LinkedBlockingDeque();//无界对象 Integer.MAX_VALUE public void put(){ while (true){ try { queue.put(count++); System.out.println("线程" + Thread.currentThread().getName() + "生产了" + ":" + count); } catch (InterruptedException e) { e.printStackTrace(); } } } public void remove(){ while (true){ Integer num = null; try { num = (Integer)queue.take(); //take } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程" + Thread.currentThread().getName() + "消费了"+num); } } public static void main(String[] args) { _MyContainer3 container = new _MyContainer3(); for (int i = 0; i < 10; i++) { //启动5个消费线程 new Thread(container::remove, i + "").start(); //启动20个生产线程 new Thread(() -> { container.put(); }, i + "").start(); } } }