While not ideal, you may be able to achieve your goals with tagged read preferences (see
http://docs.mongodb.org/ecosystem/drivers/java-replica-set-semantics/#read-preferences-and-tagging). If you give each of your replica set nodes a unique "id" (you could use any name you prefer) tag ("rs0", "rs1", "rs2", etc), you can construct a read preference that will order the application's preference for a particular node, with failover to the next preferred, and so on. You can create such a read preference like this:
ReadPreference pref = ReadPreference.secondary(new BasicDBObject("id", "rs0"),
new BasicDBObject("id", "rs1"),
new BasicDBObject("id", "rs2"));
The effect of this read preference will be to route all queries to the (one) node in the replica set that is currently a secondary and tagged with {"id" : "rs0"}, if one exists. If none exists, it will try for "rs1", and so on.
The problem with this approach is that you could go back in time without being notified, in the case of a failure of, say, the node tagged with "rs0".
If you want to make certain you don't go back in time, you could use a read preference like:
ReadPreference pref = ReadPreference.secondaryPreferred(new BasicDBObject("id", "rs0"));
This will force all queries to the secondary tagged with {"id" : "rs0"}, if one exists. If that node is down or is no longer a secondary, it will route the queries to the primary (which may be "rs0" if it was elected.
I could see this approach working for your application if you could segment it into logical units of work, and use a read preference with a different value for the "id" tag for each of these units. That way you could load balance the units of work across multiple secondaries, with the caveat of if that secondary happens to be down, queries will go to the primary, and if in addition there is no primary (say during an election), the queries will fail.
Regards,
Jeff