<!-- 附上依赖包配置 --> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency>
参考:http://blog.csdn.net/ghsau/article/details/7481142
package thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; public class WaitTest { /** * 容器的最大长度 */ private static final int listSize = 3; /** * 容器 */ private static List<String> list = new ArrayList<String>(listSize); static class ProducerThread extends Thread { /** * 生产者的id */ private int proId; /** * 当这个生产者结束后,这个值降1,表明生产者数量减少了一个 */ private CountDownLatch proCount; public ProducerThread(int proId, CountDownLatch proCount) { this.proId = proId; this.proCount = proCount; } @Override public void run() { int time = 0; while (time < 5) { synchronized (list) { while (list.size() >= listSize) { // 标记A1 try { System.out.println("**** producer proId=" + proId + ": wait begin, time=" + time + " list.size=" + list.size()); list.wait(); System.out.println("**** producer proId=" + proId + ": wait finish, time=" + time + " list.size=" + list.size()); } catch (InterruptedException e) { e.printStackTrace(); } } list.add(time++ + ":" + proId); System.out.println("------------- pro " + proId + " add ----------------"); list.notifyAll(); // 当有多个生产者时,这里会唤醒其他生产者,因此在标记A1处要用while,而不能是if } } System.out.println("producer proId=" + proId + ": end"); proCount.countDown(); } } static class ComsumerThread extends Thread { /** * 消费者id */ private int comId; /** * 当这个生产者结束后,这个值降1,表明生产者数量减少了一个 */ private CountDownLatch proCount; public ComsumerThread(int comsumerId, CountDownLatch proCount) { this.comId = comsumerId; this.proCount = proCount; } @Override public void run() { while (true) { if (proCount.getCount() == 0) { return; } synchronized (list) { while (list.size() == 0) { // 标记B1 if (proCount.getCount() == 0) { return; } try { System.out.println("##### consumer comId=" + comId + ", wait begin, list.size=" + list.size()); list.wait(); System.out.println("##### consumer comId=" + comId + ", wait end, list.size=" + list.size()); } catch (InterruptedException e) { e.printStackTrace(); } } String firstItem = list.remove(0); System.out.println("消费一个:" + firstItem + ", list.size=" + list.size()); list.notifyAll(); // 当有多个消费者时,这个notify会唤醒其他消费者,因此在标记B1处要用while,而不能是if } } } } public static void main(String[] args) { final int proCount = 10; // 生产者的数量 final int comCount = 10; // 消费者的数量 CountDownLatch countDown = new CountDownLatch(proCount); System.out.println("========================================================"); for (int nLoop = 0; nLoop < proCount; ++nLoop) { new ProducerThread(nLoop, countDown).start(); } for (int nLoop = 0; nLoop < comCount; ++nLoop) { new ComsumerThread(nLoop, countDown).start(); } } }
改进版,用await/signal/signallAll还执行
package thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class WaitTest { /** * 容器的最大长度 */ private static final int listSize = 3; /** * 容器 */ private static List<String> list = new ArrayList<String>(listSize); private static ReentrantLock lock = new ReentrantLock(); private static Condition notFull = lock.newCondition(); private static Condition notEmpty = lock.newCondition(); static class ProducerThread extends Thread { /** * 生产者的id */ private int proId; /** * 当这个生产者结束后,这个值降1,表明生产者数量减少了一个 */ private CountDownLatch proCount; public ProducerThread(int proId, CountDownLatch proCount) { this.proId = proId; this.proCount = proCount; } @Override public void run() { int time = 0; while (time < 5) { /// synchronized (list) { lock.lock(); try { while (list.size() >= listSize) { // 标记A1 try { System.out.println("**** producer proId=" + proId + ": wait begin, time=" + time + " list.size=" + list.size()); /// list.wait(); notFull.await(); System.out.println("**** producer proId=" + proId + ": wait finish, time=" + time + " list.size=" + list.size()); } catch (Exception e) { e.printStackTrace(); } } list.add(time++ + ":" + proId); notEmpty.signalAll(); System.out.println("------------- pro " + proId + " add ----------------"); /// list.notifyAll(); // 当有多个生产者时,这里会唤醒其他生产者,因此在标记A1处要用while,而不能是if } finally { lock.unlock(); } /// } } System.out.println("producer proId=" + proId + ": end"); proCount.countDown(); // 确保那些还在阻塞的消费者被signal lock.lock(); try { notEmpty.signalAll(); } finally { lock.unlock(); } } } static class ComsumerThread extends Thread { /** * 消费者id */ private int comId; /** * 当这个生产者结束后,这个值降1,表明生产者数量减少了一个 */ private CountDownLatch proCount; public ComsumerThread(int comsumerId, CountDownLatch proCount) { this.comId = comsumerId; this.proCount = proCount; } @Override public void run() { while (true) { if (proCount.getCount() == 0) { return; } /// synchronized (list) { lock.lock(); try { while (list.size() == 0) { // 标记B1 if (proCount.getCount() == 0) { System.out.println("comsumer " + comId + " return."); return; } try { System.out.println("##### consumer comId=" + comId + ", wait begin, list.size=" + list.size() + ", proCount=" + proCount.getCount()); /// list.wait(); notEmpty.await(); System.out.println("##### consumer comId=" + comId + ", wait end, list.size=" + list.size() + ", proCount=" + proCount.getCount()); } catch (InterruptedException e) { e.printStackTrace(); } } String firstItem = list.remove(0); System.out.println("消费一个:" + firstItem + ", list.size=" + list.size()); notFull.signal(); /// list.notifyAll(); // 当有多个消费者时,这个notify会唤醒其他消费者,因此在标记B1处要用while,而不能是if } finally { lock.unlock(); } /// } } } } public static void main(String[] args) { final int proCount = 10; // 生产者的数量 final int comCount = 20; // 消费者的数量 CountDownLatch countDown = new CountDownLatch(proCount); System.out.println("========================================================"); for (int nLoop = 0; nLoop < proCount; ++nLoop) { ProducerThread producerThread = new ProducerThread(nLoop, countDown); producerThread.setPriority(Thread.MIN_PRIORITY); producerThread.start(); } for (int nLoop = 0; nLoop < comCount; ++nLoop) { ComsumerThread comsumerThread = new ComsumerThread(nLoop, countDown); comsumerThread.setPriority(Thread.MAX_PRIORITY); comsumerThread.start(); } } }
用disruptor的一个例子,目前仅仅是写出例子了,还没仔细研究
package disruptor.dbreadwrite; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.concurrent.Executors; import com.lmax.disruptor.EventFactory; import com.lmax.disruptor.EventHandler; import com.lmax.disruptor.RingBuffer; import com.lmax.disruptor.dsl.Disruptor; import com.lmax.disruptor.dsl.EventHandlerGroup; class RowEvent { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } } /** * disruptor的测试类 * 参考:https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started * http://lavasoft.blog.51cto.com/62575/238613 * * 简介:生产者不断往表里写入记录,消费者不断从表里删除记录 * @author Longli * @since 2014-6-3 17:48:49 */ public class LongliTestMain { static Connection con = null; static { try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:4050/test?charactorEncoding=utf-8"; con = DriverManager.getConnection(url , "root", "123456"); } catch (Throwable e) { e.printStackTrace(); System.exit(1); } } @SuppressWarnings({ "unchecked", "unused" }) public static void main(String[] args) { Disruptor<RowEvent> disruptor = new Disruptor<RowEvent>(new EventFactory<RowEvent>() { @Override public RowEvent newInstance() { return new RowEvent(); } }, 32/* ringBuffer容量 */, Executors.newCachedThreadPool()/*线程池,线程池最后应该shutdown的*/); // 消费者行为 EventHandlerGroup<RowEvent> handlerGroup = disruptor.handleEventsWith(new EventHandler<RowEvent>() { @Override public void onEvent(RowEvent event, long sequence, boolean endOfBatch) throws Exception { long rowId = event.getId(); try { Statement delStatement = con.createStatement(); System.out.println("be to delete row with id=" + rowId); int delCount = delStatement.executeUpdate("delete from disruptor_test where id = " + rowId); System.out.println("end delete row with id=" + rowId + ", delCount=" + delCount); } catch (SQLException e) { e.printStackTrace(); } } }); disruptor.start(); // 生产者行为 RingBuffer<RowEvent> ringBuffer = disruptor.getRingBuffer(); for (int n=0; n<10000/*生产行为的次数*/; ++n) { long sequence = ringBuffer.next(); RowEvent event = ringBuffer.get(sequence); try { // insert_and_get_id是我自己写的存储过程:插入一条记录,然后获取刚刚插入记录的自增id // 参考:http://lavasoft.blog.51cto.com/62575/238613 CallableStatement prepareCall = con.prepareCall("call insert_and_get_id(?,?)"); prepareCall.setString(1, "nLoop=" + n); prepareCall.registerOutParameter(2, Types.BIGINT); prepareCall.executeUpdate(); long lastInsertId = prepareCall.getLong(2); event.setId(lastInsertId); } catch (SQLException e) { e.printStackTrace(); } finally { ringBuffer.publish(sequence); } } } }