注:我测试过,读取文件的线程读取每一行的时间是数据处理线程处理一行时间的十几倍(即生产速度快)。
结果:下面的Cache代表的是生产者线程,负责取文件中的行,Handle是数据处理线程,处理List中的行,size是两个相同大小的List的大小,cache先生产,随后handle不断取,我不理解为什么handle取的速度最后快于cache了?难道cache是读文件优先级低?
cache : Size_x : 1 Size_y : 1
cache : Size_x : 2 Size_y : 2
cache : Size_x : 3 Size_y : 3
cache : Size_x : 4 Size_y : 4
cache : Size_x : 5 Size_y : 5
cache : Size_x : 6 Size_y : 6
cache : Size_x : 7 Size_y : 7
cache : Size_x : 8 Size_y : 8
cache : Size_x : 9 Size_y : 9
cache : Size_x : 10 Size_y : 10
cache : Size_x : 11 Size_y : 11
cache : Size_x : 12 Size_y : 12
cache : Size_x : 13 Size_y : 13
cache : Size_x : 14 Size_y : 14
cache : Size_x : 15 Size_y : 15
cache : Size_x : 16 Size_y : 16
cache : Size_x : 17 Size_y : 17
cache : Size_x : 18 Size_y : 18
cache : Size_x : 19 Size_y : 19
cache : Size_x : 20 Size_y : 20
cache : Size_x : 21 Size_y : 21
cache : Size_x : 21 Size_y : 21
handle : Size_x : 21 Size_y : 21
handle : Size_x : 20 Size_y : 20
cache : Size_x : 20 Size_y : 20
handle : Size_x : 20 Size_y : 20
handle : Size_x : 19 Size_y : 19
handle : Size_x : 18 Size_y : 18
cache : Size_x : 18 Size_y : 18
handle : Size_x : 18 Size_y : 18
handle : Size_x : 17 Size_y : 17
cache : Size_x : 17 Size_y : 17
handle : Size_x : 17 Size_y : 17
handle : Size_x : 16 Size_y : 16
handle : Size_x : 15 Size_y : 15
cache : Size_x : 15 Size_y : 15
handle : Size_x : 15 Size_y : 15
handle : Size_x : 14 Size_y : 14
handle : Size_x : 13 Size_y : 13
cache : Size_x : 13 Size_y : 13
handle : Size_x : 13 Size_y : 13
handle : Size_x : 12 Size_y : 12
cache : Size_x : 12 Size_y : 12
handle : Size_x : 12 Size_y : 12
handle : Size_x : 11 Size_y : 11
handle : Size_x : 10 Size_y : 10
cache : Size_x : 10 Size_y : 10
handle : Size_x : 10 Size_y : 10
handle : Size_x : 9 Size_y : 9
cache : Size_x : 9 Size_y : 9
handle : Size_x : 9 Size_y : 9
handle : Size_x : 8 Size_y : 8
handle : Size_x : 7 Size_y : 7
cache : Size_x : 7 Size_y : 7
handle : Size_x : 7 Size_y : 7
handle : Size_x : 6 Size_y : 6
handle : Size_x : 5 Size_y : 5
cache : Size_x : 5 Size_y : 5
handle : Size_x : 5 Size_y : 5
handle : Size_x : 4 Size_y : 4
handle : Size_x : 3 Size_y : 3
cache : Size_x : 3 Size_y : 3
handle : Size_x : 3 Size_y : 3
handle : Size_x : 2 Size_y : 2
cache : Size_x : 2 Size_y : 2
handle : Size_x : 2 Size_y : 2
handle : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
handle : Size_x : 0 Size_y : 0
cache : Size_x : 1 Size_y : 1
代码:
Runnable r1 = new DataSetCacheThread();
Runnable r2 = new DataSetHandleThread();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
4 个解决方案
#1
读文件,需要IO,速度比较慢吧
#2
cache : 读取一行的时间:16235 e-6s
cache : 读取一行的时间:4742 e-6s
cache : 读取一行的时间:1003 e-6s
cache : 读取一行的时间:754 e-6s
cache : 读取一行的时间:3200 e-6s
cache : 读取一行的时间:1106 e-6s
cache : 读取一行的时间:2761 e-6s
cache : 读取一行的时间:763 e-6s
cache : 读取一行的时间:2094 e-6s
cache : 读取一行的时间:1032 e-6s
cache : 读取一行的时间:1888 e-6s
cache : 读取一行的时间:1363 e-6s
cache : 读取一行的时间:687 e-6s
cache : 读取一行的时间:2957 e-6s
cache : 读取一行的时间:604 e-6s
cache : 读取一行的时间:1021 e-6s
cache : 读取一行的时间:1809 e-6s
cache : 读取一行的时间:1857 e-6s
cache : 读取一行的时间:1298 e-6s
cache : 读取一行的时间:1416 e-6s
cache : 读取一行的时间:579 e-6s
handle : 处理一行的时间:11178 e-6s
cache : 读取一行的时间:1333 e-6s
handle : 处理一行的时间:9747 e-6s
handle : 处理一行的时间:3757 e-6s
handle : 处理一行的时间:3423 e-6s
cache : 读取一行的时间:572 e-6s
handle : 处理一行的时间:4340 e-6s
handle : 处理一行的时间:5281 e-6s
cache : 读取一行的时间:573 e-6s
handle : 处理一行的时间:3691 e-6s
handle : 处理一行的时间:6016 e-6s
handle : 处理一行的时间:3704 e-6s
cache : 读取一行的时间:1038 e-6s
handle : 处理一行的时间:4691 e-6s
handle : 处理一行的时间:3755 e-6s
handle : 处理一行的时间:5142 e-6s
handle : 处理一行的时间:4606 e-6s
cache : 读取一行的时间:1062 e-6s
handle : 处理一行的时间:5299 e-6s
handle : 处理一行的时间:4767 e-6s
cache : 读取一行的时间:17259 e-6s
handle : 处理一行的时间:20612 e-6s
handle : 处理一行的时间:5724 e-6s
handle : 处理一行的时间:3943 e-6s
cache : 读取一行的时间:583 e-6s
handle : 处理一行的时间:3285 e-6s
handle : 处理一行的时间:3181 e-6s
handle : 处理一行的时间:4385 e-6s
cache : 读取一行的时间:1340 e-6s
handle : 处理一行的时间:4015 e-6s
handle : 处理一行的时间:3537 e-6s
cache : 读取一行的时间:557 e-6s
handle : 处理一行的时间:3231 e-6s
handle : 处理一行的时间:4075 e-6s
cache : 读取一行的时间:4742 e-6s
cache : 读取一行的时间:1003 e-6s
cache : 读取一行的时间:754 e-6s
cache : 读取一行的时间:3200 e-6s
cache : 读取一行的时间:1106 e-6s
cache : 读取一行的时间:2761 e-6s
cache : 读取一行的时间:763 e-6s
cache : 读取一行的时间:2094 e-6s
cache : 读取一行的时间:1032 e-6s
cache : 读取一行的时间:1888 e-6s
cache : 读取一行的时间:1363 e-6s
cache : 读取一行的时间:687 e-6s
cache : 读取一行的时间:2957 e-6s
cache : 读取一行的时间:604 e-6s
cache : 读取一行的时间:1021 e-6s
cache : 读取一行的时间:1809 e-6s
cache : 读取一行的时间:1857 e-6s
cache : 读取一行的时间:1298 e-6s
cache : 读取一行的时间:1416 e-6s
cache : 读取一行的时间:579 e-6s
handle : 处理一行的时间:11178 e-6s
cache : 读取一行的时间:1333 e-6s
handle : 处理一行的时间:9747 e-6s
handle : 处理一行的时间:3757 e-6s
handle : 处理一行的时间:3423 e-6s
cache : 读取一行的时间:572 e-6s
handle : 处理一行的时间:4340 e-6s
handle : 处理一行的时间:5281 e-6s
cache : 读取一行的时间:573 e-6s
handle : 处理一行的时间:3691 e-6s
handle : 处理一行的时间:6016 e-6s
handle : 处理一行的时间:3704 e-6s
cache : 读取一行的时间:1038 e-6s
handle : 处理一行的时间:4691 e-6s
handle : 处理一行的时间:3755 e-6s
handle : 处理一行的时间:5142 e-6s
handle : 处理一行的时间:4606 e-6s
cache : 读取一行的时间:1062 e-6s
handle : 处理一行的时间:5299 e-6s
handle : 处理一行的时间:4767 e-6s
cache : 读取一行的时间:17259 e-6s
handle : 处理一行的时间:20612 e-6s
handle : 处理一行的时间:5724 e-6s
handle : 处理一行的时间:3943 e-6s
cache : 读取一行的时间:583 e-6s
handle : 处理一行的时间:3285 e-6s
handle : 处理一行的时间:3181 e-6s
handle : 处理一行的时间:4385 e-6s
cache : 读取一行的时间:1340 e-6s
handle : 处理一行的时间:4015 e-6s
handle : 处理一行的时间:3537 e-6s
cache : 读取一行的时间:557 e-6s
handle : 处理一行的时间:3231 e-6s
handle : 处理一行的时间:4075 e-6s
#3
这要看你在handle里面做的是什么操作,是否耗时,一般来说读取文件的耗时是比较长的,速度跟不上后面的处理线程是正常的,如果想要保持顺序就在缓存的list上加锁,然后加的地方notify一下,handle取的地方做下wait
#4
这种业务场景在我的项目里经常用,基本上用这样的逻辑:
/**
* 消费者线程,可有多个消费者实例
* 多个消费者线程共用一个数据缓存队列 queue
* 生产者通过调用消费者的静态方法 addData 把生产的数据加到队列中,并且通知所有在
* 等待数据的消费者:有东西了,可以去消费了
* 生产者和消费过生日 对 queue 进行同步
*/
public class Customer implements Runnable{
private static final Queue<YourDataClass> queue = new LinkedList<YourDataClass>();
private Thread thread = null;
private boolean running = false;
public void run(){
running = true;
while(running){
synchronied(queue){
while(running && queue.size() == 0){
queue.wait();
}
}
if(running == false)
break;
YourDataClass data = queue.poll();
// 调用消费者代码
}
}
public static void addData(YourDataClass data){
synchronized(queue){
queue.add(data);
queue.notifyAll();
}
}
public void start(){
if(thread != null)
return;
thread = new Thread(this);
thread.start();
}
public void stop(){
running = false;
synchronized(queue){
queue.notifyAll();
}
}
public static final Customer Instance = new Customer();
public Customer(){
}
}
#1
读文件,需要IO,速度比较慢吧
#2
cache : 读取一行的时间:16235 e-6s
cache : 读取一行的时间:4742 e-6s
cache : 读取一行的时间:1003 e-6s
cache : 读取一行的时间:754 e-6s
cache : 读取一行的时间:3200 e-6s
cache : 读取一行的时间:1106 e-6s
cache : 读取一行的时间:2761 e-6s
cache : 读取一行的时间:763 e-6s
cache : 读取一行的时间:2094 e-6s
cache : 读取一行的时间:1032 e-6s
cache : 读取一行的时间:1888 e-6s
cache : 读取一行的时间:1363 e-6s
cache : 读取一行的时间:687 e-6s
cache : 读取一行的时间:2957 e-6s
cache : 读取一行的时间:604 e-6s
cache : 读取一行的时间:1021 e-6s
cache : 读取一行的时间:1809 e-6s
cache : 读取一行的时间:1857 e-6s
cache : 读取一行的时间:1298 e-6s
cache : 读取一行的时间:1416 e-6s
cache : 读取一行的时间:579 e-6s
handle : 处理一行的时间:11178 e-6s
cache : 读取一行的时间:1333 e-6s
handle : 处理一行的时间:9747 e-6s
handle : 处理一行的时间:3757 e-6s
handle : 处理一行的时间:3423 e-6s
cache : 读取一行的时间:572 e-6s
handle : 处理一行的时间:4340 e-6s
handle : 处理一行的时间:5281 e-6s
cache : 读取一行的时间:573 e-6s
handle : 处理一行的时间:3691 e-6s
handle : 处理一行的时间:6016 e-6s
handle : 处理一行的时间:3704 e-6s
cache : 读取一行的时间:1038 e-6s
handle : 处理一行的时间:4691 e-6s
handle : 处理一行的时间:3755 e-6s
handle : 处理一行的时间:5142 e-6s
handle : 处理一行的时间:4606 e-6s
cache : 读取一行的时间:1062 e-6s
handle : 处理一行的时间:5299 e-6s
handle : 处理一行的时间:4767 e-6s
cache : 读取一行的时间:17259 e-6s
handle : 处理一行的时间:20612 e-6s
handle : 处理一行的时间:5724 e-6s
handle : 处理一行的时间:3943 e-6s
cache : 读取一行的时间:583 e-6s
handle : 处理一行的时间:3285 e-6s
handle : 处理一行的时间:3181 e-6s
handle : 处理一行的时间:4385 e-6s
cache : 读取一行的时间:1340 e-6s
handle : 处理一行的时间:4015 e-6s
handle : 处理一行的时间:3537 e-6s
cache : 读取一行的时间:557 e-6s
handle : 处理一行的时间:3231 e-6s
handle : 处理一行的时间:4075 e-6s
cache : 读取一行的时间:4742 e-6s
cache : 读取一行的时间:1003 e-6s
cache : 读取一行的时间:754 e-6s
cache : 读取一行的时间:3200 e-6s
cache : 读取一行的时间:1106 e-6s
cache : 读取一行的时间:2761 e-6s
cache : 读取一行的时间:763 e-6s
cache : 读取一行的时间:2094 e-6s
cache : 读取一行的时间:1032 e-6s
cache : 读取一行的时间:1888 e-6s
cache : 读取一行的时间:1363 e-6s
cache : 读取一行的时间:687 e-6s
cache : 读取一行的时间:2957 e-6s
cache : 读取一行的时间:604 e-6s
cache : 读取一行的时间:1021 e-6s
cache : 读取一行的时间:1809 e-6s
cache : 读取一行的时间:1857 e-6s
cache : 读取一行的时间:1298 e-6s
cache : 读取一行的时间:1416 e-6s
cache : 读取一行的时间:579 e-6s
handle : 处理一行的时间:11178 e-6s
cache : 读取一行的时间:1333 e-6s
handle : 处理一行的时间:9747 e-6s
handle : 处理一行的时间:3757 e-6s
handle : 处理一行的时间:3423 e-6s
cache : 读取一行的时间:572 e-6s
handle : 处理一行的时间:4340 e-6s
handle : 处理一行的时间:5281 e-6s
cache : 读取一行的时间:573 e-6s
handle : 处理一行的时间:3691 e-6s
handle : 处理一行的时间:6016 e-6s
handle : 处理一行的时间:3704 e-6s
cache : 读取一行的时间:1038 e-6s
handle : 处理一行的时间:4691 e-6s
handle : 处理一行的时间:3755 e-6s
handle : 处理一行的时间:5142 e-6s
handle : 处理一行的时间:4606 e-6s
cache : 读取一行的时间:1062 e-6s
handle : 处理一行的时间:5299 e-6s
handle : 处理一行的时间:4767 e-6s
cache : 读取一行的时间:17259 e-6s
handle : 处理一行的时间:20612 e-6s
handle : 处理一行的时间:5724 e-6s
handle : 处理一行的时间:3943 e-6s
cache : 读取一行的时间:583 e-6s
handle : 处理一行的时间:3285 e-6s
handle : 处理一行的时间:3181 e-6s
handle : 处理一行的时间:4385 e-6s
cache : 读取一行的时间:1340 e-6s
handle : 处理一行的时间:4015 e-6s
handle : 处理一行的时间:3537 e-6s
cache : 读取一行的时间:557 e-6s
handle : 处理一行的时间:3231 e-6s
handle : 处理一行的时间:4075 e-6s
#3
这要看你在handle里面做的是什么操作,是否耗时,一般来说读取文件的耗时是比较长的,速度跟不上后面的处理线程是正常的,如果想要保持顺序就在缓存的list上加锁,然后加的地方notify一下,handle取的地方做下wait
#4
这种业务场景在我的项目里经常用,基本上用这样的逻辑:
/**
* 消费者线程,可有多个消费者实例
* 多个消费者线程共用一个数据缓存队列 queue
* 生产者通过调用消费者的静态方法 addData 把生产的数据加到队列中,并且通知所有在
* 等待数据的消费者:有东西了,可以去消费了
* 生产者和消费过生日 对 queue 进行同步
*/
public class Customer implements Runnable{
private static final Queue<YourDataClass> queue = new LinkedList<YourDataClass>();
private Thread thread = null;
private boolean running = false;
public void run(){
running = true;
while(running){
synchronied(queue){
while(running && queue.size() == 0){
queue.wait();
}
}
if(running == false)
break;
YourDataClass data = queue.poll();
// 调用消费者代码
}
}
public static void addData(YourDataClass data){
synchronized(queue){
queue.add(data);
queue.notifyAll();
}
}
public void start(){
if(thread != null)
return;
thread = new Thread(this);
thread.start();
}
public void stop(){
running = false;
synchronized(queue){
queue.notifyAll();
}
}
public static final Customer Instance = new Customer();
public Customer(){
}
}