class TaskScheduer {

    public void schedule(final IErrorHandler iErrorHandler, long timeout, ITimeoutHandler iTimeoutHandler, final ITasksFinishCallback iTasksFinishCallback) {
        final AtomicInteger taskDoneCounter = new AtomicInteger(0);
        final int taskCount = mTasks.size();
        for (final LaunchTask task : mTasks) {
            task.runOn().execute(new Worker(iErrorHandler, task, mTasks, new Worker.TaskDoneCallback() {
                @Override
                public void onTaskDone() {
                    if (taskDoneCounter.addAndGet(1) == taskCount && iTasksFinishCallback != null) {
                        iTasksFinishCallback.onTasksFinished();
                    }
                }
            }));
        }
        TaskDelayChecker.delayCheckTaskAlive(mTasks, timeout, iTimeoutHandler);
    }

}

class TaskScheduerTest {

    @Test
    public void schedule3() throws Exception {

        final Executor executor = Executors.newCachedThreadPool();
        final CountDownLatch downLatch = new CountDownLatch(3);
        final long[] taskStartTime = {0, 0, 0};
        final long[] taskEndTime = {0, 0, 0};
        LaunchTask task0 = TaskFactory.create("task0", 1000, new ArrayList<String>(), executor, new TestTaskCallback() {
            @Override
            public void taskStart() {
                taskStartTime[0] = System.nanoTime();
            }

            @Override
            public void taskEnd() {
                taskEndTime[0] = System.nanoTime();
                downLatch.countDown();
            }
        });
        LaunchTask task1 = TaskFactory.create("task1", 1000, Collections.singletonList("task0"), executor, new TestTaskCallback() {
            @Override
            public void taskStart() {
                taskStartTime[1] = System.nanoTime();
            }

            @Override
            public void taskEnd() {
                taskEndTime[1] = System.nanoTime();
                downLatch.countDown();
            }
        });
        LaunchTask task2 = TaskFactory.create("task2", 1000, Arrays.asList("task0", "task1"), executor, new TestTaskCallback() {
            @Override
            public void taskStart() {
                taskStartTime[2] = System.nanoTime();
            }

            @Override
            public void taskEnd() {
                taskEndTime[2] = System.nanoTime();
                downLatch.countDown();
            }
        });
        new TaskScheduer(Arrays.asList(task2, task1, task0)).schedule(null, 0, null);
        downLatch.await();
        //1 依赖 0 ,2 依赖 1 ,2 依赖0
        Assert.assertTrue(taskEndTime[0] < taskStartTime[1]);
        Assert.assertTrue(taskEndTime[1] < taskStartTime[2]);
    }

}