比如说我数据库中有10万条email数据,我想写个多线程的程序把他们发送出去取数据库记录时候如何取呢?如果一次性取出都放到List里,然后放到个一个多线程的程序里去发送,我觉得list的数据会太多。如:
   ExecutorService exec = Exectors.newFixedThreadPool(10);
   List<Email> list = 数据库中所有的记录;   
   foreach( Email s : list) {
        exec.execute(new SendMail(s));  //发送邮件
   }   class void SendMail extends Thread {
        private Email email;
        public SendMail(Email email) {
             this.email = email;
        }
        //是否要同步
        void run {
             发送邮件。。
             TimeUnit.MILLISECONDS.sleep(20); //是否需要?
        }        set....
        get.....
   }   这样就要一次性取出所有的记录,
可以不可以开10个线程,每个线程各子取1万条记录进行发送呢,就像5个搬运工同时干活一样?如何实现呢??

解决方案 »

  1.   

    开五个线程,
    开一个全局计数器,计算发了多少个(百条)邮件,这里计数器用Integer,便于锁定。
    开一个缓冲500条邮件的缓冲集合。
    线程1发送:1~100,发送完,锁定计数器操作(计数器+1,从数据库中取下一百条记录放于缓冲中的1-100位置)
    线程2发送:101—200,发送完,锁定计数器操作(计数器+1,从数据库中取下一百条记录放于缓冲中的101—200位置)
    线程3发送:201—300,类似上
    线程4发送:301—400,类似上
    线程5发送:401—500,类似上所有从数据库中取一百条记录用一个统一的同步方法实现。over
      

  2.   

    package Thread;public class TwoThread {
    public static void main(String[] args) {
    Queue q=new Queue ();//new出一个q:后面的两个线程都是用的同一个q,保证一个put一个get
    Producer p=new Producer (q);//让new出的p去往q里面put
    Customer c=new Customer (q);//让new出的c从q中get
    p.start();//p和q开始的顺序并不报错
    c.start();

    }
    }
    class Producer extends Thread
    {
    Queue q;
    public Producer(Queue q) {
    this.q=q;//给成员变量赋值,再一调运q的put方法
    }
    @Override
    public void run() {
    for (int i = 0; i < 10; i++) {
    q.put(i);//此处只是让q去put  10次
    System.out.println("Producer put "+i);//并且输出本次放的是第几杯
    }
    }
    }
    class Customer extends Thread
    {
    Queue q;
    public Customer(Queue q) {
    this.q=q;//给成员变量赋值,再一调运q的get方法
    }
    @Override
    public void run() {
    while (true) {//死循环:只要q里面有,就去get
    //get方法有返回值,返回值就是producer所put的数量
    //此处也不需要去考虑是第几杯
    //在Queue中的value解决可这一问题:
    //put中的I赋给value,get方法有返回值就value的值
    System.out.println("Customer get "+q.get());
    //如果循环完了,就跳出循环,否则线程不会自己结束
    if (q.value==9) {
    break;
    }
    }

    }
    }
    class Queue
    {
    int value;
    boolean bFull=false;
    public synchronized void put (int i)//在producer中的put方法中就是将其I传进来
    {
    if (!bFull) {//条件为真(如果没满,就倒水)
    value=i;//给value赋值,现在有几杯水
    bFull=true;//满了
    notify();//唤醒其他线程(让customer去get)
    }
    try {
    wait();//告诉customer去get后自己等待customer的get结束
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    public synchronized int get()
    {
    if (!bFull) {//如果没满就等待,如果满了就不进    **这就是为什么main里面谁先开始不报错的原因**
    //get和put方法中的if条件判断起到了至关重要的作用
    try {
    wait();
    } catch (InterruptedException e) {

    e.printStackTrace();
    }
    }
    bFull =false;//赋值为没满
    notify();//唤醒producer去put
    return value;//get的返回值就是put的时候给value赋的值
    }
    }