日期:2014-05-20  浏览次数:20959 次

让线程里一段代码重复执行
一个线程接收不定时发来的网络发来的包,存在List<Packet>里,另一个线程从list里取出包解析,并移除,并将其存入数据库,每50个批处理一次,接收线程收到包抓包程序回调就可以向list里添加 解析线程主动从list取 如果取空了就得死循环 while(true)检测list.size何时大于0 
  但我不想死循环检测 问:能不能当第一个线程有新包来时 通知第二个线程 notifyAll 或 singalAll会唤醒哪个线程不确定 notify 或 singal 也不确定。只开两个线程可能都是解析线程(线程池executor),不用线程池的话如何让执行完的线程再重复执行 new Thread的话先的线程可能还没执行完
  以下模拟有问题的代码 注释中也提出疑问 是不是不该多个线程共用一个PrepareStatment(未同步)


package test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadDao {

public static void main(String[] args) throws Exception {
Dao dao=new Dao();
dao.conn();
ExecutorService pool = Executors.newFixedThreadPool(2);

for(int i=0;i<100;i++){//模拟网络发来的100个包
pool.execute(new Runnable() {

@Override
public void run() {
System.out.print("c");

}
});//模拟接受包 是不是应该放到循环100次外面?
pool.execute(new Parse(dao));//取出解析包  是不是应该放到循100次外面?

}
}


}
class Parse implements Runnable{
public Dao dao;

public Parse(Dao dao) {
this.dao = dao;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(500);
dao.save();//可能有2个线程同时访问同一个dao对象
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Dao{
static int cnt=0;
PreparedStatement ps;Connection c;
public void conn() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","","");
c.setAutoCommit(false);
ps = c.prepareStatement("insert into u values(?)");
}

public void save() throws Exception{
ps.setInt(1, 33);
ps.addBatch();//可能有2个线程同时访问同一个ps对象 结果容易出错
cnt++;
if(cnt%50==0){
ps.executeBatch();
c.commit();
ps.clearBatch();
}
// Thread.sleep(500);
}
}



------解决方案--------------------
典型的生产者,消费者问题,搜索一下,网上很多例子的。
------解决方案--------------------
  信  号  灯  。
------解决方案--------------------
给你随便找了个例子 http://www.javacodegeeks.com/2011/09/java-concurrency-tutorial-semaphores.html