See Refactoring for a full discussion. A coroutine is a variant of the idea of a subroutine where the two routines call each other in a peer relationship rather than master-slave. Multiple calls of the coroutine lead to it resuming where it left off, rather than recursively starting at the top again. Java uses subroutines, not coroutines, so you're not going to easily create code that uses that approach. The classes java.io.PipedInputStream and java.io.PipedOutputStream can help you implement this in a multi-threaded way.
Some methods are better for large cases than small ones.
If the last thing a routine does is recursively call itself, you can instead adjust the arguments and branch back to the top, saving the overhead of stacking contexts and making another procedure call. Introduce an Explicit Stack Recursion works by having a hidden call stack. A routine can simulate this by maintaining its own stack. When a recursive call would be made, push the current state onto the stack, adjust the arguments, and branch to the top. This is a pretty dramatic change in a procedure, and can definitely reduce the clarity of the routine.