I would suggest having a single thread that is responsible for grabbing tasks.
There are many, many possible strategies. One is simply to have 4 queues, and try to cycle between them. Another is to stick tasks into a priority queue (typically implemented with a heap data structure), but if you do that then be aware that all of the higher priority tasks will be taken before any lower priority tasks. A third is to use a priority queue based on age so you can take the oldest request first - then make high priority requests artificially old. (I could suggest the age of the oldest thing in the queue plus a constant term.)
One general point to keep in mind. If you assign sufficient capacity, your queues will likely remain reasonably short. If your capacity is insufficient, then queues will grow without bound and in the long run you can think of your queueing problem as one of triage rather than prioritization. But if possible, it often works well to try to increase capacity instead of being clever in prioritization.