When passing in a collection of sObjects to a Queueable what values are used?

sObjects (and other objects, for that matter) that are instance variables in Queueables and in Batch Apex classes are serialized and stored, and then deserialized at the time the Asynchronous Apex is executed. Field values for sObjects are not refreshed unless your code performs an explicit SOQL query to do so.

Take this Queueable, for example:

public class TestQueueable implements Queueable {
    private Account a;

    public TestQueueable(Account a) {
        this.a = a;
    }

    public void execute(System.QueueableContext qc) {
        System.debug('Account Name is ' + a.Name);
    }
}

If you run in Anonymous Apex

Account a = new Account(Name = 'Test');
insert a;

System.enqueueJob(new TestQueueable(a));

a.Name = 'ACME';
update a;

Which Account Name prints in the Queueable, when it executes after the Anonymous Apex transaction completes?

It's important to note that the Queueable (or future, or batch) doesn't start executing until this transaction, the Anonymous Apex we're running, commits successfully and without a rollback. Chronologically, the update DML fires before the Queueable even begins executing.

Here's what we get back:

15:42:44:004 USER_DEBUG [9]|DEBUG|Account Name is Test

One consequence of this feature is that Queueables and Batch Apex cannot have non-serializable member variables. Messaging.SingleEmailMessage, for example, is not serializable. If we'd written

Messaging.SingleEmailMessage a = new Messaging.SingleEmailMessage();
System.enqueueJob(new TestQueueable(a));

we would get back

System.SerializationException: Not Serializable: Messaging.SingleEmailMessage


Just to add what David said.

Future / Queueable are just tools that allow us to do another job asynchronously after the main transaction has ended. It's intentionally made dumb so that developers can make it do what they want. There is no SLA for future/queuable calls. They can happen the next second or can happen after 30 mins or even an hour.

Now there can be various use cases like you have to sync data to very transaction oriented external system and you use Queuable. Now even if you delete that record(before queuable has executed), you still want the entity to be sent for audit purpose. Here Queueable gives you that power

If you want the latest data, you can always query it. It suits the need of both Data at the time of main DML happened as well as the time when the actual call is made.