Safely pass a list of objects to a thread that reschedules itself
<p>I have a thread that is responsible for purging old data from a MySQL database. We delete in batches so the db isn't consumed if there's a large purge, so the thread does the purge, waits for a few seconds, and then calls itself again to continue the purge (if there's any records left).</p>

<p>My issue is that we allow people to setup multiple rules for what needs to be purged. In an old system that didn't do anything in batches, we'd simply iterate through each "purge rule" and run the queries.</p>

<p>However, now that we have a system where the thread schedules itself again, I can remove rules from the <code>ArrayList</code> anymore, due to a <code>ConcurrentModificationException</code></p>

<p>I have an <code>ArrayList&lt;QueryParameters&gt;</code> that we iterate. If there are no records left to purge, we should remove the rule from the list, so that the next time the thread runs it doesn't repeat it.</p>

<p>How can I properly remove the rule from the list but not get the CME? I guess I could a ConcurrentHashMap but I don't want really want to store a key->value.</p>

<p>The code is a plugin to a larger java app, we're using their thread schedulder, just FYI.</p>

<p>I've tried both ways to iterate the arraylist, a for loop and using an iterator</p>

<pre><code>public class PurgeTask implements Runnable {

    private Prism plugin;
    private ArrayList&lt;QueryParameters&gt; paramList;
    private int total_records_affected = 0, cycle_rows_affected = 0;
    private int purge_tick_delay;

    /**
     * 
     * @param plugin
     */
    public PurgeTask( Prism plugin, ArrayList&lt;QueryParameters&gt; paramList, int purge_tick_delay ){
        this.plugin = plugin;
        this.paramList = paramList;
        this.purge_tick_delay = purge_tick_delay;
    }


    /**
     * 
     */
    public void run(){
        if(paramList.size() &gt; 0){
            ActionsQuery aq = new ActionsQuery(plugin);
            // Execute in batches so we don't tie up the db with one massive query
            for (Iterator&lt;QueryParameters&gt; it = paramList.iterator(); it.hasNext(); ) {
                QueryParameters param = it.next();

                cycle_rows_affected = aq.delete(param);
                plugin.debug("Purge cycle cleared " + cycle_rows_affected + " rows.");
                total_records_affected += cycle_rows_affected;

                // If nothing (or less than the limit) has been deleted this cycle, we need to move on
                if( cycle_rows_affected == 0 || cycle_rows_affected &lt; plugin.getConfig().getInt("prism.purge.records-per-batch") ){

                    // Log final count of cleared records
                    plugin.log("Cleared " + total_records_affected + " rows from the database. Using:" + param.getOriginalCommand() );
                    total_records_affected = 0;

                    // Remove the purge rule from the list so we don't repeat
                    paramList.remove(param);

                } else {

                    // Items we're deleted. Leave params in queue and re-schedule this task
                    plugin.deleteTask = plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, new PurgeTask( plugin, paramList, purge_tick_delay ), purge_tick_delay);

                }
            }
        }
    }
}
</code></pre>
