将一个runnable的输出作为其他几个的输入

时间:2017-05-15 02:28:33

标签: java multithreading testing

我有一个用例,我不断测试工作流程。我有一个mysql数据库的条目来存储学生记录,检索它,用一些细节更新它,然后最后删除它。

为了测试这些工作流程,我将每个步骤作为单独的方法。现在,为了连续测试它,我可能正在考虑让整个工作流程在多线程模型中执行。

我遇到的困难是我如何让其他操作(获取,更新和删除)等到创建操作完成。我正在查找Thread.join()并通知方法,但我不确定这是否是最优雅的方式。

以下是我目前的代码示例(相当天真的版本):

public class Test {
    public static void main(String[] args) {

        while (true) {
            String studentId = createStudent();
            Thread.sleep(1000);
            Runnable calls[] = new Runnable {
                () -> getStudent(studentId),
                () -> updateStudent(studentId),
                () -> delete(studentId)
            };

            for (Runnable call: calls) {
                call.run();
            }
        }

    }

    private String createStudent() {
        ...
        ...
        ...
        return studentId;
    }

    private void getStudent(String studentId) 
        ...
        ...
        ...
    }

    private void updateStudent(String studentId) 
        ...
        ...
        ...
    }

    private void deleteStudent(String studentId) 
        ...
        ...
        ...
    }

}

我很确定我介绍睡眠的方式是一个非常天真的实现,绝对不推荐。如果我不得不使用通知或加入,是否有最佳实践建议我可以查找?

1 个答案:

答案 0 :(得分:0)

这可以通过线程等待和通知线程通信方式或使用倒计时锁存来解决。下面的例子说明倒计时锁存方式。

public class ConditionAwaiter {

    private final Callable<Boolean> asyncCondition;
    private final Condition condition;
    private final CountDownLatch latch;
    private Throwable throwable = null;

    public ConditionAwaiter(Callable<Boolean> asyncCondition, Condition condition) {
        this.asyncCondition = asyncCondition;
        this.condition = condition;
        this.latch = new CountDownLatch(1);
    }

    public void await() {
        boolean processCompleted = false;
        try {
            new WaitThread(asyncCondition, condition).start();
            Duration maxWaitTime = condition.getWaitDuration();

            if (maxWaitTime.getValue() == WaitStrategy.WAIT_FOREVER) {
                latch.await();
                processCompleted = true;
            } else {
                processCompleted = latch.await(maxWaitTime.getValue(), maxWaitTime.getTimeUnit());
            }

        } catch (Exception e) {
            throwable = e;
        } finally {
            if (throwable != null || !processCompleted) {
                throw new IllegalStateException("Not able to complete on time");

            }
        }
    }

    class WaitThread extends Thread {
        private final Callable<Boolean> asyncCondition;
        private final Condition condition;
        private Duration pollInterval;
        private Lock lock = new ReentrantLock();
        private java.util.concurrent.locks.Condition lockCondition = lock.newCondition();

        public WaitThread(Callable<Boolean> asyncCondition, Condition condition) {
            this.asyncCondition = asyncCondition;
            this.condition = condition;
            pollInterval = condition.getPollInterval();
        }

        @Override
        public void run() {
            lock.lock();
            try {
                try {
                    while (!asyncCondition.call()) {
                        lockCondition.await(pollInterval.getValue(), pollInterval.getTimeUnit());
                    }
                } catch (InterruptedException e) {

                }

                if (asyncCondition.call()) {
                    latch.countDown();
                }
            } catch (Exception e) {
                throwable = e;
            } finally {
                lock.unlock();
            }
        }

    }

}