一个线程接收不定时发来的网络发来的包,存在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);
}
}
但我不想死循环检测 问:能不能当第一个线程有新包来时 通知第二个线程 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);
}
}
还是采用同步方法吧。read() {
operate(data, 1);
}send() {
operate(data, 2);
}synchronized operate(data, type) {
// 读
if (type == 1) {
} else if (type == 2) { // 送
}
}我只是随便写一下,读到数据,存到List后,就可以继续读下一个数据了。
这样的同步并发还是挺高的,我测试过线程来读与送,能达到4W多并发执行,应该不存在这里阻塞你的执行。
待高人帮你提出更优解决方案。