@Test
public void testOffer002() throws Exception {

    int capacity = 1;
    final long timeout = 20000;
    final TimeUnit unit = TimeUnit.MILLISECONDS;
    DataValueObject obj1 = new DataValueObject("hoge1");
    boolean result1 = false;
    final CountDownLatch threadSync = new CountDownLatch(1);
    final ArrayBlockingQueueEx<DataValueObject> queue = new ArrayBlockingQueueEx<DataValueObject>(capacity);
    // キューをいっぱいにする
    result1 = queue.offer(obj1, timeout, unit);
    assertTrue(result1);
    // 別スレッドでofferを実行（キューがいっぱいなので待ちになる）
    ErrorFeedBackThread thread01 = new ErrorFeedBackThread() {
        @Override
        public void doRun() throws Exception {
            DataValueObject obj2 = new DataValueObject("hoge2");
            // 待ち状態をつくる
            long timeStart = System.currentTimeMillis();
            threadSync.countDown();
            try {
                queue.offer(obj2, timeout, unit);
                throw new RuntimeException("An exception did not occur within a definite period of time.");
            } catch (InterruptedException e) {
                // 期待通り
            }
            long timeEnd = System.currentTimeMillis();
            long timeDiff = timeEnd - timeStart;
            // 約1000ミリ秒の待ち確認(50ミリ秒の誤差を許容)
            if (timeDiff < 950) {
                throw new RuntimeException("An exception did not occur within a definite period of time.");
            }
        }
    };
    thread01.start();
    threadSync.await();
    TimeUnit.MILLISECONDS.sleep(1000);
    // 割り込み
    thread01.interrupt();
    thread01.throwErrorOrExceptionIfThrown();
}