我们如何使用轮转的方式多线程?(How can we use multi-thread in rou

2019-09-20 10:18发布

我想读的10个邮件帐户的封未读邮件在多线程的方式。

但是,如果线程池的大小为5,则5个线程会从线程池使用。 每个线程会读一个邮件帐户。 所以一旦Thread_1读了第一信箱,就应该读mailbox_6。 然后线程2将读取mailbox_7。

当所有的邮件帐户已经被读取一次,该周期从1日的邮件帐户启动。

我们怎样才能做到这一点在Java中?

Answer 1:

这应该是很容易的。 您创建5个线程固定线程池,然后您提交的10个作业池 - 1元每个用户的电子邮件帐户:

// create a thread pool with 5 workers
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// submit all 10 user email accounts to the pool to be processed in turn
for (UserEmail userEmail : userEmailsToProcess) {
    threadPool.submit(new EmailProcessor(userEmail));
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
...
// here's our runnable class which does the actual work
public class EmailProcessor implements Runnable {
    private UserEmail userEmail;
    public MyJobProcessor(UserEmail userEmail) {
        this.userEmail = userEmail;
    }
    public void run() {
        // read the user email
        ...
    }
}

UserEmail类可容纳的电子邮件“读取”或可能的帐户名称或某事的文件名。 这将是由你来弄清楚如何代表邮件帐户和邮件被读取。

[从评论:]

我有10个邮箱一样.. mailbox1 ... mailbox10,现在我已经从线程池5线程,所以线程1将获取任何邮箱,以便让我们假设它会挑mailbox1,然后线程2会挑mailbox2,thread3会挑mailbox3,thread4会挑mailbox4和thread5会挑mailbox5,现在当线程1(与已经定义的特定时间段)将释放,那么它应该是挑mailbox6 - mailbox10,任何人这是尚未读取它不应该mailbox1挑选任何邮箱 - mailbox5,达所有邮箱其中尚未阅读。

哦,我明白了。 一种解决方案是有一个正在睡觉和起床,每隔一段时间,看看邮箱的任何邮件调度线程。 如果他们这样做,然后它科目作业到线程池为该邮箱被读取。 一旦邮箱已读线程再次进入,并要求下一个邮箱来处理。 调度线程将继续邮箱添加到线程池中,直到被告知停止。

如果有大量的上下文中的EmailProcessor那么你可以有你的线程池,但他们可以从消费BlockingQueue<File>或一些东西,告诉他们什么邮箱需要注意。



Answer 2:

跟踪正在阅读的电子邮件帐户。 例如像这样定义的东西,

//total number of email accounts that need to be read.
private int noOfEmails=10;

//the thread pool that is used to read the emails
private ExecutorService threadPool = Executors.newFixedThreadPool(5);

//the tracker array that keeps track of the emails that 
//are already read. This array is cleared only after all 10
//emails are read. 
private ArrayList<String> emailTracker=new ArrayList<String>(noOfEmails);

//any changes to emailTracker should be synchronized as 
//this is a common data shared between all 5 threads.
private Object syncObject=new Object();

在Runnable的执行,检查emailTracker包含您的电子邮件帐户标识,如果是的话那意味着它已经看过,所以回来,等到emailTracker被清除。 当阅读所有10个电子邮件帐户将被清除。

        if(emailTracker.contains(email.identifier))
        {
            return;
        }

        //read email.
        email.read();
        //simple synchronization.
        synchronized (syncObject)
        {
            //read email
            emailTracker.add(email.identifier);
            //if all emails are read, clear the tracker
            //This will allow reading of all the emails 
            //once again.
            if(emailTracker.size()==noOfEmails)
            {
                emailTracker.clear();
            }

        }


Answer 3:

如何简单地创建一个并发的(或同步的,没有多大意义在这种情况下)的任务集合(也许队列)。 每个任务都会从电子邮件帐户加载所需的数据。 然后让每个线程接受一个任务,从收藏,直到它是空的。

每个线程都会有这个集合的引用,并会做它一个循环。 虽然集合不为空,采取从它的任务和处理。



Answer 4:

执行人可能不是最佳的解决方案,但在这里为了简单起见,我会用灰色的代码的变化。 为了不断扫描你的10个邮箱,你可以做以下虽然你必须添加一些代码来处理干净终止:

// Create one semaphore per mailbox
Semaphore semaphores[] = new Semaphore[10]
for (int s = 0; s < semaphores.length; s ++) {
    semaphores[s] = new Semaphore(1);
}

 // create a thread pool with 5 workers
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// submit all 10 user email accounts to the pool to be processed in turn
for (int i = 0; i < 5; i ++) {
    threadPool.submit(userEmailsToProcess, semaphores);
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
...

// here's our runnable class which does the actual work
public class EmailProcessor implements Runnable {
    private UserEmail userEmailToProcess[];
    private Semaphore semaphores[];
    public MyJobProcessor(UserEmail userEmailToProcess[], Semaphore semaphores[]) {
        this.userEmailsToProcess = userEmailToProcess;
        this.semaphores = semaphores;
    }
    public void run() {
        while (true) {   // you could use a semaphore here to test program termination instead
            for (int s = 0; s < semaphores.size; s ++) {
                if (semaphores[s].tryAcquire()) {
                    UserEmail email = userEmailToProcess[s];
                    // read the user email
                    …
                    semaphores[s].release();
                }
            }
        }
    }
}

这是一个快速和肮脏的解决方案,是不是100%的公平,但它会为任意数量的线程和邮箱的工作。 在你有10封电子邮件和5名工人特殊情况下,你可以让每个线程连续扫描邮箱的一个子集,即线程1检查mailbox1然后mailbox2,线程2检查mailbox3然后mailbox4,...这样一来,因为有你可以没有信号灯做不争



Answer 5:

三居我相信你要在以下循环方式来执行它们:

线程1:1,6等线程2:2,7 Thread3:3,8 Thread4:4,9 Thread5:5,10

首先,这是不是意味着什么线程,如果你想在那样的顺序来执行它们。 其次,我不认为这是可能的线程池。 如果你仍然希望他们那么这里是我用于执行循环的方式线程,你可能会改变根据您的需要的解决方案:公共类EmailRoundRobin {公共对象[]锁;

    private static class EmailProcessor implements Runnable {
        private final Object currentLock;
        private final Object nextLock;
        private UserEmail userEmail;
        public EmailProcessor (UserEmail userEmail,, Object currentLock, Object nextLock) {
           this.userEmail = userEmail;
       this.currentLock = currentLock;
           this.nextLock = nextLock;
        }
        @Override
        public void run() {
           try {
                work = //reading email
                while ( work != null) {
                    try {
                        currentLock.wait();
                        // Do your work here.
                    }
                    catch(InterruptedException e) {}
                    synchronized(nextLock) {
                        nextLock.notify();
                    }
                }//while ends
            } catch (IOException e) {
                e.printStackTrace();
        }
        synchronized(nextLock) {
            nextLock.notify(); /// Ensures all threads exit at the end
        }
    }

public EmailRoundRobin(int numberOfAccountsToRead) {
    locks = new Object[numberOfAccountsToRead];

    //Initialize lock instances in array.
    for(i = 0; i < numberOfAccountsToRead; ++i) locks[i] = new Object();
    //Create threads
    int j;
    for(j=0; j<(numberOfAccountsToRead-1); j++ ){
        Thread linePrinterThread = new Thread(new EmailProcessor(emailInfo + "Temp" + j,locks[j],locks[j+1]));
        linePrinterThread.start();
    }
    Thread lastLinePrinterThread = new Thread(new EmailProcessor(emailInfo + "Temp" + j,locks[numberOfFilesToRead-1],locks[0]));
    lastLinePrinterThread.start();
}

public void startProcessing() {
    synchronized (locks[0]) {
        locks[0].notify();
    }
}

public static void main(String[] args) {
    EmailRoundRobin emailRoundRobin = new EmailRoundRobin(4);
    emailRoundRobin.startPrinting();
}

}

我有(这种采取从我的回答[这个问题] 轮循方式在Java中运行的线程 )! 其中有类似的要求。 有使用移相器这个问题的答案也提到还有一个选项。



Answer 6:

我得到的回答自己,它很简单,我已经使用的ExecutorService,它通过其唯一的管理。



文章来源: How can we use multi-thread in round robin manner?