今天看了项目的源码。看到了每个方法都用synchronized 标注的方法,代码也懒得看了,幸好我们用户少,越来越少。。。。不需要那么高的并发。。。
闲话不多说,早上说了观察者模式。突然想到了是不是可以用生产消费模式。一边做任务,一边处理任务,中间存任务状态,会不会耦合度少点,而且能做到线程安全(后来看了下,没有做到,必须在task 线程里面搞安全。回头多看看多线程和并发的知识)
上代码:
1.message 类,就是生产者和消费者中间那个东西。一个生产一个消费。。。。。
package testProductIssue;
public class Message {
private String msg;
public Message(String msg){
this.msg = msg;
}
public String getMsg(){
return msg;
}
}
2.生产者:
package testProductIssue;
import java.util.concurrent.BlockingQueue;
public class Product implements Runnable{
private BlockingQueue<Message> que ;
public Product(BlockingQueue<Message> que){
this.que = que;
}
@Override
public void run() {
for(int i=0 ; i <10;i++){
Message e = new Message("message:"+i);
try {
que.put(e);
System.out.println("this is P "+e.getMsg());
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Message e = new Message("exit");
try {
que.put(e);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
3.消费者
package testProductIssue;
import java.util.concurrent.BlockingQueue;
public class Custom implements Runnable{
private BlockingQueue<Message> que;
public Custom(BlockingQueue<Message> que){
this.que = que;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Message msg ;
//这里我看了下BlockingQueue的take方法,调用一次这个方法,这个queue里面的
//东西就被取走了,所以就直接写在while里面了,这个如果设置成永远等下去,就等于
//我上一个里面那个wait了。。感觉一个效果。
while((msg=que.take()).getMsg()!="exit"){
//先让他休息一下,要不可能那边放上去还没来得及打印到命令行这边就输出了,会造成困扰
Thread.sleep(2000);
System.out.println("this is C "+msg.getMsg());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.测试类
package testProductIssue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class TestIssue {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Message> msg = new ArrayBlockingQueue<Message>(5);
Thread pro = new Thread(new Product(msg));
Thread cus = new Thread(new Custom(msg));
pro.start();
cus.start();
pro.join();
}
}
这里的BlockingQueue要说一下,这是concurrent 包下面的一个接口,后面ArrayBlockingQueue是一个实现类,这个有什么特点呢。首先是线程安全的。而且有一个特点就是如果这个queue里面空的,则去操作会处于阻塞状态,如果这个queue是满的,添加操作处于阻塞状态,这里我设置queue的大小是5,下面我吧设置成2的输出到控制台 就能体会到这个阻塞的感觉了。。。
this is P message:0
this is P message:1
this is P message:2
this is C message:0 //取出一个数
this is P message:3 //才能放进去一个
this is C message:1 //取出一个
this is P message:4 //才能放进去一个
this is C message:2
this is P message:5
this is C message:3
this is P message:6
this is C message:4
this is P message:7
this is C message:5
this is P message:8
this is C message:6
this is P message:9
this is C message:7
this is C message:8
this is C message:9
然后 生产者消费者就是这样呀,两个线程 一个生产 一个消费,把东西放到超市(中间的那个queue) 然后各取所需。额貌似就这样,刚刚吃过晚饭,晚上回家继续研究,现在脑子里面啥都没有。。想起来再更新吧。。。。
当然,生产者消费者模式还有另一种实现,就是在中间缓存处不使用BlockingQueue 而是用其他的存储单位,这样的话,很容易造成线程不同步的问题,就是我们所说的多线程并发导致的数据不同步了,我网上看了下,可以用volatile关键字来定义容器中中得message,这样存取就不会乱掉。因为volatile是永远从内存中读得。现在想想这个关键字和 threadlocal完全是对立吧,一个是暴力同步内存中得。一个是保存对象副本。分场合来使用这两个东西吧。。。