Example usage for java.lang Thread yield

List of usage examples for java.lang Thread yield

Introduction

In this page you can find the example usage for java.lang Thread yield.

Prototype

public static native void yield();

Source Link

Document

A hint to the scheduler that the current thread is willing to yield its current use of a processor.

Usage

From source file:fs.MainWindow.java

public void CrossValidation(int nr_executions, float percent_trainning, int selector) throws IOException {
    String penalization_type = (String) jCB_PenalizationCV.getSelectedItem();
    float alpha = ((Double) jS_AlphaCV.getValue()).floatValue();
    float q_entropy = ((Double) jS_QEntropyCV.getValue()).floatValue();
    float beta = ((float) jSliderBetaCV.getValue() / 100);

    //if selected criterion function is CoD, q_entropy = 0
    if (jCB_CriterionFunctionCV.getSelectedIndex() == 1) {
        q_entropy = 0;//from w  w  w  . j av a  2  s  . c om
    } //CoD

    if (q_entropy < 0 || alpha < 0) {
        //entrada de dados invalida.
        JOptionPane.showMessageDialog(null,
                "Error on parameter value:" + "The values of q-entropy and Alpha must be positives.",
                "Application Error", JOptionPane.ERROR_MESSAGE);
        return;
    }

    dataset = new DefaultCategoryDataset();
    double rate = 0;
    int n = Main.maximumValue(Md, 0, lines - 1, 0, columns - 2) + 1;
    int c = Main.maximumValue(Md, 0, lines - 1, columns - 1, columns - 1) + 1;

    jProgressBarCV.setValue(1);

    int total_samples = (int) (lines * percent_trainning);

    trainingset = new float[total_samples][columns];
    testset = new float[lines - total_samples][columns];
    //testset = new float[total_samples][columns];

    char[][] strainingset = null;
    char[][] stestset = null;

    jProgressBarCV.setValue(3);

    float ex = (96 / nr_executions);

    /* calculating the estimated time to be completed in a
    computer of 2 GHz*/
    int combinations = MathRoutines.numberCombinations(columns - 1, 1);

    double estimatedTime = (0.0062 + 3.2334e-7 * Mo.length) * combinations * Math.log(combinations)
            / Math.log(2);

    estimatedTime *= nr_executions;

    System.out.println("Estimated time to finish: " + estimatedTime + " s");
    int answer = JOptionPane.showConfirmDialog(this,
            "Estimated time to finish: " + estimatedTime + " s.\n " + "Do you want to continue?",
            "Cross Validation", JOptionPane.YES_NO_OPTION);
    if (answer == 1) {
        jProgressBarCV.setValue(0);
        return;
    }

    //vetor com os resultados da selecao de caracteristica.
    int resultsetsize = 1;
    //vetor com os resultados da selecao de caracteristica.

    for (int executions = 0; executions < nr_executions; executions++) {
        if (flag_quantization) {
            Validation.GenerateSubSets(Md, percent_trainning, trainingset, testset);
            //Preprocessing.quantizecolumnsavg(trainingset, (Integer) jS_QuantizationValue.getValue(), true, has_labels);
            //Preprocessing.quantizecolumnsavg(testset, (Integer) jS_QuantizationValue.getValue(), false, has_labels);
        } else {
            Validation.GenerateSubSets(Mo, percent_trainning, trainingset, testset);
        }

        strainingset = MathRoutines.float2char(trainingset);
        stestset = MathRoutines.float2char(testset);

        int maxfeatures = (Integer) jS_MaxSetSizeCV.getValue();
        if (maxfeatures <= 0) {
            JOptionPane
                    .showMessageDialog(
                            this, "Error on parameter value: The"
                                    + " Maximum Set Size be a integer value greater" + " or equal to 1.",
                            "Application Error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        FS fs = new FS(strainingset, n, c, penalization_type, alpha, beta, q_entropy, resultsetsize);
        if (selector == 1) {
            fs.runSFS(false, maxfeatures);
        } else if (selector == 3) {
            fs.runSFFS(maxfeatures, -1, null);
        } else if (selector == 2) {
            fs.runSFS(true, maxfeatures); /* a call to SFS is made in order to get
                                          the ideal dimension for the exhaustive search. */
            int itmax = fs.itmax;
            FS fsPrev = new FS(strainingset, n, c, penalization_type, alpha, beta, q_entropy, resultsetsize);
            for (int i = 1; i <= itmax; i++) {
                fs = new FS(strainingset, n, c, penalization_type, alpha, beta, q_entropy, resultsetsize);
                fs.itmax = i;
                fs.runExhaustive(0, 0, fs.I);
                if (fs.hGlobal == 0) {
                    break;
                }
                if (fs.hGlobal < fsPrev.hGlobal) {
                    fsPrev = fs;
                } else {
                    fs = fsPrev;
                    break;
                }
            }
        }
        if (executions == 0) {
            jTA_SelectedFeaturesCV.setText("Execution " + (executions + 1)
                    + " - Global Criterion Function Value: " + fs.hGlobal + "\n");
        } else {
            jTA_SelectedFeaturesCV.append("\n\nExecution " + (executions + 1)
                    + " - Global Criterion Function Value: " + fs.hGlobal + "\n");
        }

        jTA_SelectedFeaturesCV.append("Selected Features: ");
        for (int i = 0; i < fs.I.size(); i++) {
            jTA_SelectedFeaturesCV.append(fs.I.elementAt(i) + " ");
        }

        jProgressBarCV.setValue(jProgressBarCV.getValue() + (int) (ex / 4));
        Thread.yield();

        /* CLASSIFICADOR. */
        Classifier clas = new Classifier();
        clas.classifierTable(strainingset, fs.I, n, c);

        jProgressBarCV.setValue(jProgressBarCV.getValue() + (int) (ex / 4));
        Thread.yield();

        for (int i = 0; i < clas.table.size(); i++) {
            double[] tableLine = (double[]) clas.table.elementAt(i);
            double instance = (Double) clas.instances.elementAt(i);
            System.out.print(instance + " ");
            for (int j = 0; j < c; j++) {
                System.out.print((int) tableLine[j] + " ");
            }
            System.out.println();
            Thread.yield();
        }
        //stestset = strainingset;
        double[] instances = clas.classifyTestSamples(stestset, fs.I, n, c);
        jProgressBarCV.setValue(jProgressBarCV.getValue() + (int) (ex / 4));
        Thread.yield();
        if (executions == 0) {
            jTA_SaidaCV.setText("Execution " + (executions + 1) + " - Correct Labels  -  Classified Labels - "
                    + "Classification Instances\n");
        } else {
            jTA_SaidaCV.append("\n\nExecution " + (executions + 1)
                    + " - Correct Labels  -  Classified Labels - " + "Classification Instances\n");
        }
        double hits = 0;
        for (int i = 0; i < clas.labels.length; i++) {
            //char correct_char = stestset[i].charAt(collumns-1);
            int correct_label = stestset[i][columns - 1];
            //int correct_label = correct_char;
            int classified_label = clas.labels[i];
            jTA_SaidaCV.append("\n" + correct_label + "  -  " + classified_label + "  -  " + instances[i]);
            if (correct_label == classified_label) {
                hits++;
            }
        }
        double hit_rate = hits / clas.labels.length;
        if (rate > 0) {
            rate = (rate + hit_rate) / 2;
        } else {
            rate = hit_rate;
        }
        jTA_SaidaCV.append("\nrate of hits = " + hit_rate);
        dataset.addValue(1 - rate, "Error Cross Validation", String.valueOf(executions + 1));

        jProgressBarCV.setValue(jProgressBarCV.getValue() + (int) (ex / 4));
        Thread.yield();
    }
    Chart.LineChart(dataset,
            "Cross Validation Error with " + (int) (percent_trainning * 100) + "% of samples on Training Set",
            "Number of executions", "Mean Errors", false, 0, 0);
    jProgressBarCV.setValue(100);
    Thread.yield();
}

From source file:com.nttec.everychan.ui.MainActivity.java

private void restartActivity() {
    MainApplication.getInstance().tabsSwitcher.currentId = null;
    MainApplication.getInstance().tabsSwitcher.currentFragment = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // https://code.google.com/p/android/issues/detail?id=93731
        Async.runAsync(new Runnable() {
            @Override//from   w w  w.  j  a  va 2 s  .c o m
            public void run() {
                try {
                    Thread.sleep(10);
                } catch (Exception e) {
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        CompatibilityImpl.recreateActivity(MainActivity.this);
                    }
                });
            }
        });
    } else {
        final Intent i = new Intent(this.getIntent());
        this.finish();
        Async.runAsync(new Runnable() {
            @Override
            public void run() {
                //?  ?? ? activity; onDestroy() ? -> onCreate() 
                while (!isDestroyed)
                    Thread.yield();
                Async.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        MainActivity.this.startActivity(i);
                    }
                });
            }
        });
    }
}

From source file:com.cloudera.beeswax.BeeswaxServiceImpl.java

/**
 * Create a new BeeswaxServiceImpl./*w  w  w  . j  a v  a  2s.c o m*/
 *
 * @param dtHost The Hue host (ip or hostname).
 * @param dtPort The port Desktop runs on.
 * @param dtHttps Whether Desktop is running https.
 * @param queryLifetime The life time of a cached query.
 */
public BeeswaxServiceImpl(String dtHost, int dtPort, boolean dtHttps, long queryLifetime) {
    LogContext.initLogCapture();
    this.executor = Executors.newCachedThreadPool(new NamingThreadFactory("Beeswax-%d"));
    this.runningQueries = new ConcurrentHashMap<String, RunningQueryState>();
    this.queryLifetime = queryLifetime;

    if (dtPort == -1) {
        this.notifyUrl = null;
    } else {
        String protocol;
        if (dtHttps) {
            try {
                // Disable SSL verification. HUE cert may be signed by untrusted CA.
                SSLContext sslcontext = SSLContext.getInstance("SSL");
                sslcontext.init(null, new DummyX509TrustManager[] { new DummyX509TrustManager() },
                        new SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
            } catch (NoSuchAlgorithmException ex) {
                LOG.warn("Failed to disable SSL certificate check " + ex);
            } catch (KeyManagementException ex) {
                LOG.warn("Failed to disable SSL certificate check " + ex);
            }
            DummyHostnameVerifier dummy = new DummyHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(dummy);
            protocol = "https";
        } else {
            protocol = "http";
        }
        this.notifyUrl = protocol + "://" + dtHost + ":" + dtPort + NOTIFY_URL_BASE;
    }

    // A daemon thread that periodically evict stale RunningQueryState objects
    Thread evicter = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                long now = System.currentTimeMillis();
                for (Map.Entry<String, RunningQueryState> entry : runningQueries.entrySet()) {
                    RunningQueryState rqState = entry.getValue();
                    //safe guard against small value of lifetime, only clean FINISHED or EXCEPTION state
                    if ((rqState.state == QueryState.FINISHED || rqState.state == QueryState.EXCEPTION)
                            && rqState.getAtime() + getQueryLifetime() < now) {
                        String id = entry.getKey();
                        runningQueries.remove(id);
                        LOG.debug("Removed " + rqState.toString());
                        Thread.yield(); // be nice
                    }
                }

                LogContext.garbageCollect(getQueryLifetime());

                long wakeup = now + EVICTION_INTERVAL;
                while (System.currentTimeMillis() < wakeup) {
                    try {
                        Thread.sleep(EVICTION_INTERVAL);
                    } catch (InterruptedException e) {
                    }
                }
            }
        }
    }, "Evicter");
    evicter.setDaemon(true);
    evicter.start();
}

From source file:org.trianacode.taskgraph.service.RunnableTask.java

/**
 * Order a unit to stop, resets the unit to its pre-run state
 *///from   w  w w .  j  a  va  2s. com
public void reset() {
    super.reset();

    getProperties().getEngine().execute(new Runnable() {
        public void run() {

            boolean handled = false;

            do {
                synchronized (THREAD_LOCK) {
                    if (threadstate != UNSTABLE) {
                        if (threadstate == IN_PROCESS) {
                            unit.stopping();
                            thread.interrupt();
                        } else {
                            unit.reset();
                            wakeups.clear();

                            executionReset();
                        }

                        handled = true;
                    } else {
                        Thread.yield();
                    }
                }
            } while (!handled);
        }
    });
}

From source file:edu.illinois.enforcemop.examples.jbosscache.PessimisticSyncReplTxTest.java

public void testPutTxWithRollback() throws Exception {
    final CacheSPI<Object, Object> c2 = this.cache1;
    Thread t1 = new Thread() {
        public void run() {
            TransactionManager tm;//from   w  ww  .ja v a 2s. c o m

            try {
                lock.acquire();
                tm = beginTransaction();
                c2.put("/a/b/c", "age", 38);
                c2.put("/a/b/c", "age", 39);
                lock.release();

                Thread.sleep(100);
                lock.acquire();
                tm.rollback();
                lock.release();
            } catch (Throwable ex) {
                ex.printStackTrace();
                t1_ex = ex;
            } finally {
                lock.release();
            }
        }
    };

    Thread t2 = new Thread() {
        public void run() {
            TransactionManager tm;

            try {
                sleep(200);
                Thread.yield();
                lock.acquire();
                tm = beginTransaction();
                assertNull(cache2.get("/a/b/c", "age"));// must be null as not yet
                                                        // committed
                lock.release();

                Thread.sleep(100);
                lock.acquire();
                assertNull(cache2.get("/a/b/c", "age"));// must be null as rolledback
                tm.commit();
                lock.release();
            } catch (Throwable ex) {
                ex.printStackTrace();
                t2_ex = ex;
            } finally {
                lock.release();
            }
        }
    };

    // Let the game start
    t1.start();
    t2.start();

    // Wait for thread to die but put an insurance of 5 seconds on it.
    t1.join();
    t2.join();
    if (t1_ex != null) {
        fail("Thread1 failed: " + t1_ex);
    }
    if (t2_ex != null) {
        fail("Thread2 failed: " + t2_ex);
    }
}

From source file:LinkedTransferQueue.java

/**
 * Spins/yields/blocks until node s is matched or caller gives up.
 *
 * @param s the waiting node/*from   www  .  j  av  a2s .  com*/
 * @param pred the predecessor of s, or s itself if it has no
 * predecessor, or null if unknown (the null case does not occur
 * in any current calls but may in possible future extensions)
 * @param e the comparison value for checking match
 * @param timed if true, wait only until timeout elapses
 * @param nanos timeout in nanosecs, used only if timed is true
 * @return matched item, or e if unmatched on interrupt or timeout
 */
private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
    long lastTime = timed ? System.nanoTime() : 0L;
    Thread w = Thread.currentThread();
    int spins = -1; // initialized after first item and cancel checks
    ThreadLocalRandom randomYields = null; // bound if needed

    for (;;) {
        Object item = s.item;
        if (item != e) { // matched
            assert item != s;
            s.forgetContents(); // avoid garbage
            return this.<E>cast(item);
        }
        if ((w.isInterrupted() || (timed && nanos <= 0)) && s.casItem(e, s)) { // cancel
            unsplice(pred, s);
            return e;
        }

        if (spins < 0) { // establish spins at/near front
            if ((spins = spinsFor(pred, s.isData)) > 0)
                randomYields = ThreadLocalRandom.current();
        } else if (spins > 0) { // spin
            --spins;
            if (randomYields.nextInt(CHAINED_SPINS) == 0)
                Thread.yield(); // occasionally yield
        } else if (s.waiter == null) {
            s.waiter = w; // request unpark then recheck
        } else if (timed) {
            long now = System.nanoTime();
            if ((nanos -= now - lastTime) > 0)
                LockSupport.parkNanos(this, nanos);
            lastTime = now;
        } else {
            LockSupport.park(this);
        }
    }
}

From source file:org.opencms.staticexport.CmsAfterPublishStaticExportHandler.java

/**
 * Exports all template resources found in a list of published resources.<p>
 * /*from   ww w.  j  a v a  2s  .  c  o m*/
 * @param cms the cms context, in the root site as Export user
 * @param publishedTemplateResources list of potential candidates to export
 * @param report an I_CmsReport instance to print output message, or null to write messages to the log file    
 */
protected void exportTemplateResources(CmsObject cms, List<String> publishedTemplateResources,
        I_CmsReport report) {

    CmsStaticExportManager manager = OpenCms.getStaticExportManager();
    int size = publishedTemplateResources.size();
    int count = 1;

    if (LOG.isDebugEnabled()) {
        LOG.debug(Messages.get().getBundle().key(Messages.LOG_EXPORT_TEMPLATES_1, new Integer(size)));
    }
    report.println(Messages.get().container(Messages.RPT_STATICEXPORT_TEMPLATE_RESOURCES_BEGIN_0),
            I_CmsReport.FORMAT_HEADLINE);

    StringBuffer cookies = new StringBuffer();
    // now loop through all of them and request them from the server
    Iterator<String> i = publishedTemplateResources.iterator();
    while (i.hasNext()) {
        String rfsName = i.next();
        CmsStaticExportData data = null;
        try {
            data = manager.getVfsNameInternal(cms, rfsName);
        } catch (CmsVfsResourceNotFoundException e) {
            String rfsBaseName = rfsName;
            int pos = rfsName.lastIndexOf('_');
            if (pos >= 0) {
                rfsBaseName = rfsName.substring(0, pos);
            }
            try {
                data = manager.getVfsNameInternal(cms, rfsBaseName);
            } catch (CmsVfsResourceNotFoundException e2) {
                if (LOG.isInfoEnabled()) {
                    LOG.info(Messages.get().getBundle().key(Messages.LOG_NO_INTERNAL_VFS_RESOURCE_FOUND_1,
                            new String[] { rfsName }));
                }
            }
        }
        if (data != null) {
            data.setRfsName(rfsName);
            report.print(
                    org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SUCCESSION_2,
                            new Integer(count++), new Integer(size)),
                    I_CmsReport.FORMAT_NOTE);
            report.print(Messages.get().container(Messages.RPT_EXPORTING_0), I_CmsReport.FORMAT_NOTE);
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1,
                    rfsName));
            report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
        } else {
            // no valid resource found for rfs name (already deleted), skip it
            continue;
        }

        try {
            CmsResource resource = data.getResource();
            try {
                Collection<String> detailPages = CmsDetailPageUtil.getAllDetailPagesWithUrlName(cms, resource);
                for (String detailPageUri : detailPages) {
                    String altRfsName = manager.getRfsName(cms, detailPageUri);
                    CmsStaticExportData detailData = new CmsStaticExportData(data.getVfsName(), altRfsName,
                            data.getResource(), data.getParameters());
                    exportTemplateResource(detailData, cookies);
                }
            } catch (CmsException e) {
                LOG.error(e.getLocalizedMessage(), e);
            }

            int status = exportTemplateResource(data, cookies);

            // write the report
            if (status == HttpServletResponse.SC_OK) {
                report.println(
                        org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
                        I_CmsReport.FORMAT_OK);
            } else if (status == HttpServletResponse.SC_NOT_MODIFIED) {
                report.println(
                        org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SKIPPED_0),
                        I_CmsReport.FORMAT_NOTE);
            } else if (status == HttpServletResponse.SC_SEE_OTHER) {
                report.println(
                        org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_IGNORED_0),
                        I_CmsReport.FORMAT_NOTE);
            } else {
                report.println(org.opencms.report.Messages.get()
                        .container(org.opencms.report.Messages.RPT_ARGUMENT_1, new Integer(status)),
                        I_CmsReport.FORMAT_OK);
            }
        } catch (IOException e) {
            report.println(e);
        }
        //don't lock up the CPU exclusively - allow other Threads to run as well 
        Thread.yield();
    }
    report.println(Messages.get().container(Messages.RPT_STATICEXPORT_TEMPLATE_RESOURCES_END_0),
            I_CmsReport.FORMAT_HEADLINE);
}

From source file:com.ecyrd.jspwiki.ReferenceManager.java

/**
 * This 'deepHashCode' can be used to determine if there were any
 * modifications made to the underlying to and by maps of the
 * ReferenceManager. The maps of the ReferenceManager are not
 * synchronized, so someone could add/remove entries in them while the
 * hashCode is being computed./*from www . ja v  a 2s.co m*/
 *
 * @return Sum of the hashCodes for the to and by maps of the
 *         ReferenceManager
 * @since 2.3.24
 */
//
//   This method traps and retries if a concurrent
//   modifcaition occurs.
//   TODO: It is unnecessary to calculate the hashcode; it should be calculated only
//         when the hashmaps are changed.  This is slow.
//
public int deepHashCode() {
    boolean failed = true;
    int signature = 0;

    while (failed) {
        signature = 0;
        try {
            signature ^= m_referredBy.hashCode();
            signature ^= m_refersTo.hashCode();
            failed = false;
        } catch (ConcurrentModificationException e) {
            Thread.yield();
        }
    }

    return signature;
}

From source file:com.pingtel.sipviewer.SIPViewerFrame.java

protected Vector importSipfile(String importFilename, String filterName) throws Exception {
    File importFile = new File(importFilename);
    String tempFilePrefix = importFile.getName();
    String tempFilename;/* w  w  w . j  ava2 s. c  om*/
    Vector vData = null;

    File tempFile = File.createTempFile(tempFilePrefix, ".xml");
    tempFilename = tempFile.getAbsolutePath();

    String sysCommand = new String(filterName + " if=" + importFilename + " of=" + tempFilename);
    System.out.println("cmd: " + sysCommand);

    Thread.yield();
    Process convertProc = Runtime.getRuntime().exec(sysCommand);

    if (tempFilename != null) {
        int convertResult = convertProc.waitFor();
        System.out.println("conversion result: " + convertResult);

        if (convertResult == 0) {
            // Conversion succeeded. Read the temporary output file
            // and return.
            try {
                vData = SipBranchData.getSipBranchDataElements(new File(tempFilename).toURL());

                tempFile.delete();
            } catch (Exception ex) {
                System.err.println("Bad file " + tempFilename);
                ex.printStackTrace();
            }
        } else {
            // We do not delete the temp file so we can figure out what
            // went wrong.
            System.out.println("conversion failed");
        }
    }

    return vData;
}

From source file:org.akubraproject.txn.derby.TestTransactionalStore.java

/**
 * Stress test the stuff a bit.//from w  ww . j a  va  2 s .  c o m
 */
@Test(groups = { "blobs" }, dependsOnGroups = { "init" })
public void stressTest() throws Exception {
    // get our config
    final int numFillers = Integer.getInteger("akubra.txn.test.numFillers", 0);
    final int numReaders = Integer.getInteger("akubra.txn.test.numReaders", 10);
    final int numWriters = Integer.getInteger("akubra.txn.test.numWriters", 10);
    final int numObjects = Integer.getInteger("akubra.txn.test.numObjects", 10);
    final int numRounds = Integer.getInteger("akubra.txn.test.numRounds", 10);

    long t0 = System.currentTimeMillis();

    // "fill" the db a bit
    for (int b = 0; b < numFillers / 1000; b++) {
        final int start = b * 1000;

        doInTxn(new ConAction() {
            public void run(BlobStoreConnection con) throws Exception {
                for (int idx = start; idx < start + 1000; idx++) {
                    Blob b = con.getBlob(URI.create("urn:blobStressTestFiller" + idx), null);
                    setBody(b, "v" + idx);
                }
            }
        }, true);
    }

    long t1 = System.currentTimeMillis();

    // set up
    Thread[] writers = new Thread[numWriters];
    Thread[] readers = new Thread[numReaders];
    boolean[] failed = new boolean[] { false };

    final boolean[] testDone = new boolean[] { false };
    final int[] lowIds = new int[numWriters];
    final int[] highId = new int[] { 0 };

    // start/run the writers
    for (int t = 0; t < writers.length; t++) {
        final int tid = t;
        final int start = t * numRounds * numObjects;

        writers[t] = doInThread(new ERunnable() {
            @Override
            public void erun() throws Exception {
                for (int r = 0; r < numRounds; r++) {
                    final int off = start + r * numObjects;

                    doInTxn(new ConAction() {
                        public void run(BlobStoreConnection con) throws Exception {
                            for (int o = 0; o < numObjects; o++) {
                                int idx = off + o;
                                URI id = URI.create("urn:blobStressTest" + idx);
                                String val = "v" + idx;

                                Blob b = getBlob(con, id, null);
                                createBlob(con, b, val);
                            }
                        }
                    }, true);

                    synchronized (testDone) {
                        highId[0] = Math.max(highId[0], off + numObjects);
                    }

                    doInTxn(new ConAction() {
                        public void run(BlobStoreConnection con) throws Exception {
                            for (int o = 0; o < numObjects; o++) {
                                int idx = off + o;
                                URI id = URI.create("urn:blobStressTest" + idx);
                                String val = "v" + idx;

                                Blob b = getBlob(con, id, val);
                                deleteBlob(con, b);
                            }
                        }
                    }, true);

                    synchronized (testDone) {
                        lowIds[tid] = off + numObjects;
                    }
                }
            }
        }, failed);
    }

    // start/run the readers
    for (int t = 0; t < readers.length; t++) {
        readers[t] = doInThread(new ERunnable() {
            @Override
            public void erun() throws Exception {
                final Random rng = new Random();
                final int[] found = new int[] { 0 };

                while (true) {
                    final int low, high;
                    synchronized (testDone) {
                        if (testDone[0])
                            break;

                        high = highId[0];

                        int tmp = Integer.MAX_VALUE;
                        for (int id : lowIds)
                            tmp = Math.min(tmp, id);
                        low = tmp;
                    }

                    if (low == high) {
                        Thread.yield();
                        continue;
                    }

                    doInTxn(new ConAction() {
                        public void run(BlobStoreConnection con) throws Exception {
                            for (int o = 0; o < numObjects; o++) {
                                int idx = rng.nextInt(high - low) + low;
                                URI id = URI.create("urn:blobStressTest" + idx);
                                String val = "v" + idx;

                                Blob b = con.getBlob(id, null);
                                if (b.exists()) {
                                    assertEquals(getBody(b), val);
                                    found[0]++;
                                }
                            }
                        }
                    }, true);
                }

                if (found[0] == 0)
                    System.out.println("Warning: this reader found no blobs");
            }
        }, failed);
    }

    // wait for things to end
    for (int t = 0; t < writers.length; t++)
        writers[t].join();

    synchronized (testDone) {
        testDone[0] = true;
    }

    for (int t = 0; t < readers.length; t++)
        readers[t].join();

    long t2 = System.currentTimeMillis();

    // remove the fillers again
    for (int b = 0; b < numFillers / 1000; b++) {
        final int start = b * 1000;

        doInTxn(new ConAction() {
            public void run(BlobStoreConnection con) throws Exception {
                for (int idx = start; idx < start + 1000; idx++)
                    con.getBlob(URI.create("urn:blobStressTestFiller" + idx), null).delete();
            }
        }, true);
    }

    long t3 = System.currentTimeMillis();

    System.out.println("Time to create " + numFillers + " fillers: " + ((t1 - t0) / 1000.) + " s");
    System.out.println("Time to remove " + numFillers + " fillers: " + ((t3 - t2) / 1000.) + " s");
    System.out.println("Time to run test (" + numWriters + "/" + numRounds + "/" + numObjects + "): "
            + ((t2 - t1) / 1000.) + " s");

    assertFalse(failed[0]);
}