同步、可见、多线程、线程的池化思想
练习一
自定义容器,提供新增元素(add)和获取元素数量(size)方法。
启动两个线程。线程1向容器中新增10个数据。线程2监听容器元素数量,当容器元素数量为5时,线程2输出信息并终止。
/** * wait notify */ package concurrent.t02; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; public class Test_02 { public static void main(String[] args) { final Test_02_Container t = new Test_02_Container(); final Object lock = new Object(); new Thread(new Runnable(){ @Override public void run() { synchronized (lock) { if(t.size() != 5){ try { lock.wait(); // 线程进入等待队列。 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("size = 5"); lock.notifyAll(); // 唤醒其他等待线程 } } }).start(); new Thread(new Runnable() { @Override public void run() { synchronized (lock) { for(int i = 0; i < 10; i++){ System.out.println("add Object to Container " + i); t.add(new Object()); if(t.size() == 5){ lock.notifyAll(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } } }).start(); } } class Test_02_Container{ List<Object> container = new ArrayList<>(); public void add(Object o){ this.container.add(o); } public int size(){ return this.container.size(); } }
练习二
(生产者消费者模式):
自定义同步容器,容器容量上限为10。可以在多线程中应用,并保证数据线程安全。
/** * 生产者消费者 * wait¬ify * wait/notify都是和while配合应用的。可以避免多线程并发判断逻辑失效问题。 */ package concurrent.t04; import java.util.LinkedList; import java.util.concurrent.TimeUnit; public class TestContainer01<E> { private final LinkedList<E> list = new LinkedList<>(); private final int MAX = 10; private int count = 0; public synchronized int getCount(){ return count; } public synchronized void put(E e){ while(list.size() == MAX){ try { this.wait(); } catch (InterruptedException e1) { e1.printStackTrace(); } } list.add(e); count++; this.notifyAll(); } public synchronized E get(){ E e = null; while(list.size() == 0){ try{ this.wait(); } catch (InterruptedException e1) { e1.printStackTrace(); } } e = list.removeFirst(); count--; this.notifyAll(); return e; } public static void main(String[] args) { final TestContainer01<String> c = new TestContainer01<>(); for(int i = 0; i < 10; i++){ new Thread(new Runnable() { @Override public void run() { for(int j = 0; j < 5; j++){ System.out.println(c.get()); } } }, "consumer"+i).start(); } try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for(int i = 0; i < 2; i++){ new Thread(new Runnable() { @Override public void run() { for(int j = 0; j < 25; j++){ c.put("container value " + j); } } }, "producer"+i).start(); } } }