<!-- 附上依赖包配置 -->
<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);
}
}
}
}