From the Blue Book (OpenGL Superbible 8th7th ed., pp. 662f.):
You can have multiple contexts and share data between them, but that isn't very effective. The approach sketched in the other answer (one render thread - mutliple data generation threads) is surely the best practice.
You can have buffer objects to your application's needs and pass pointers around between threads and synchronize between threads and OpenGL calls. See OpenGL documentation for its synchronization functionalities.
You can also create commands for OpenGL by packing parameters into buffers and signal the main thread to turn them into OpenGL calls. This approach builds data structures in the generating threads and sends them to the main thread for analysis, to choose between varying functionalities and to hand them over to OpenGL. See glDrawElementsInstancedBaseVertexBaseInstance() to find out which data can be parametrized in that way.
The rest is programming :-)