The defining feature of “green threads” is that the threads are managed in userspace, not by a kernel. Green threads are often managed cooperatively, but to some degree it is also possible to schedule green threads preemptively in userspace.
In practice, modern “green threads” implementations tend to use cooperative scheduling on top of a pool of native threads, which are scheduled preemptively by the OS. In particular, it is nowadays common for programmers to describe possible suspension points in a program with async/await keywords.
But cooperative scheduling does not require the programmer to explicitly yield, since such suspension points could also be regularly inserted by a compiler or runtime (which leaves the programmer with the thread-like semantics since execution could be suspended at nearly any point). In particular, the JVM runtime does a lot of bookkeeping on top of normal code execution. In addition to suspending execution of the main program for scheduling purposes, such suspension capabilities are needed for optimizing a currently running function and for stop-the-world garbage collectors. The CPython runtime is arguably an example of pseudo-cooperatively scheduled native threads: while multiple native threads can be started, running Python code internally acquires the Global Interpreter Lock so only one thread at a time will be making progress. This means that certain functions are guaranteed to complete atomically as with a cooperatively scheduled approach.