There is absolutely no reason why single-threaded can't perform equally well or even better than multi-threaded here.
1) As already stated, don't poll all the objects, just have an update queue, sorted by next update time. Objects that can do with less frequent updates get scheduled further down the time line than those that need rapid updates. Stagger the updates too, either with a random factor, or a hashed value, to ensure you're performing a roughly equal number of updates each time.
2) Split up the update routine according to purpose and importance. eg. Animation and physics are essentially cosmetic, and can be ignored if a player isn't nearby. Pathfinding may be unimportant for a distant peasant the player doesn't care about, but very important for a monster the player deliberately trapped behind a rock, so do pathfinding before moving it. With this sort of thing in mind, you can pass these parameters to the update function and let the object decide what is appropriate.
3) Create abstract updates. Moving from A to B should require low-level pathfinding for a nearby creature, but can probably be adequately handled by simple line interpolation for a distant one. Scheduling systems are great here: if an NPC is marked as being in the Inn at 9-11pm each day, and you're nowhere near that NPC, there's no need to worry about how it gets to the Inn. Just teleport it there whenever its Update function is called between 9 and 11.
Quote:What about all other objects that are not visible, how do you pull the rope? As applying to "I need to be updated once per game hour if the player is far away, once per minute if the player is nearby, and once per frame if I'm in view".
Upon updating a given object, the game should know how long it is likely to be before another update is needed, so it can push the object back onto the queue with a given time in mind. The only thing you then have to worry about is promoting objects in importance when you approach them, so ensure you have a way to pull them to the front of the queue. One simple implementation method: make sure that the object has a reference to its position in the queue, so than an 'emergency update' can pull it out of that structure quickly. You can obviously get a list of local objects from your octtree.
I don't think you'll need a book on this to be honest - just make sure your object updates are parameterised and staggered according to their need, and that you can handle infrequent abstract updates as well as fine-grained concrete ones.