方式一:借助wait() notify()实现生产者攒够N个队列,消费者再消费
优点:对于擅长 块处理 的消费者线程来说,明显提高性能,而且消费者wait,可以把CPU空置给生产者。
相比于下面方式二,不会导致CPU的空转,和消费者线程的浪费。
提出方式一的问题背景是生产者负责实时接收消息,攒够1000个后,通知消费者线程调用neo4j接口,插入图数据库。
package test;
import java.util.ArrayList;
public class Test2 {
static ArrayList
static ArrayList
static ArrayList
static ArrayList
public int flag=0;
public static void main(String[] args) throws InterruptedException {
provider = a;
consumer = b;
Test2 test2 = new Test2();
Producer2 p = new Producer2(test2);
Consumer2 c = new Consumer2(test2);
Thread t1 = new Thread(p);
t1.start();
Thread t2 = new Thread(c);
t2.start();
t1.join();
System.out.println("aa");
t2.join();
System.out.println("a");
for (int i = 0; i < a.size(); i++) {
System.out.println(a.get(i));
}
System.out.println("b");
for (int i = 0; i < b.size(); i++) {
System.out.println(b.get(i));
}
}
synchronized ArrayList
ArrayList
if (provider.size() <= 10)
wait(200);
tmp = provider;
provider = consumer;
consumer = tmp;
flag=(flag+1)%2;
System.out.println("queue "+flag+" has "+consumer.size()+" wait");
return consumer;
}
synchronized void set(int i) {
provider.add(i);
System.out.println(flag+":生产了:" + i);
if (provider.size() > 10)
notify();
}
}
class Producer2 implements Runnable {
private Test2 bank;
public Producer2(Test2 bank) {
this.bank = bank;
}
public void run() {
for (int i = 0; i < 200; i++) {
bank.set(i);
try {
Thread.sleep((int) (Math.random() * 2));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer2 implements Runnable {
private Test2 bank;
public Consumer2(Test2 bank) {
this.bank = bank;
}
public void run() {
for (int i = 0; i < 50; i++) {
ArrayList
try {
queue = bank.get();
for (int j = 0; j < queue.size(); j++) {
System.out.println("消费了:" + queue.get(j));
Thread.sleep((int) (Math.random() * 2));
}
queue.clear();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
方式二:ReenTrantLock实现只要消费队列为空,就抢占式交换队列(此时可能生产者队列为空或者很少)
优点:这种方式消费者实时性高,并且一直不会阻塞。
缺点:如果生产者速度小于消费者,那么会频繁进入临界区进行交换,导致性能消耗。而且如果生产者队列,长时间为空,则消费者线程进入无限空转之中。
package test;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
private static ReentrantLock lock = new ReentrantLock();
static ArrayList
static ArrayList
static ArrayList
static ArrayList
public static void main(String[] args) throws InterruptedException {
provider=a;
consumer=b;
Producer p = new Producer();
Consumer c = new Consumer();
Thread t1=new Thread(p);
t1.start();
Thread t2=new Thread(c);
t2.start();
t1.join();
t2.join();
System.out.println("a");
for(int i=0;i
System.out.println("b");
for(int i=0;i
}
static ArrayList
ArrayList
lock.lock();
try {
tmp = provider;
provider = consumer;
consumer = tmp;
} finally {
lock.unlock();
}
return consumer;
}
static void set(int i) {
lock.lock();
try {
provider.add(i);
} finally {
lock.unlock();
}
}
}
class Producer implements Runnable {
public void run() {
for (int i = 0; i < 200; i++) {
Test.set(i);
System.out.println("生产了:" + i);
try {
Thread.sleep((int) (Math.random() * 2));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
public void run() {
for (int i = 0; i < 40; i++) {
ArrayList
System.out.println("consumer");
for (int j = 0; j < queue.size(); j++) {
System.out.println("消费了:" + queue.get(j));
try {
Thread.sleep((int) (Math.random() * 2));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.clear();
}
}
}