Synchronous VS Asynchronous
Synchronous
      It executes immediately and runs in single thread
      User has to wait until the process has to be completed
      Used to process smaller jobs
      Triggers are used to execute these jobs
Use Case
      In my previous project there is an object called Interactions where it is used to update the
       case details associated with their names. In this object there is particular field called
       participants where it runs through an apex class, when user enter any name, it should fetch
       data from that class so here user has to wait for the result
Asynchronous
      It executes in separate thread
      User doesn’t require to wait until the process is completed
       Used for long running and delayed operations
Use Case
      Likewise, my previous project, new users will register through workday with that information
       a user account will be created in salesforce so here a batch class is scheduled which runs
       every day at 2am as it creates worker account in salesforce here user doesn’t require to wait
       until account has to be created and it can process large volume of data in single run
Types of Asynchronous methods
      Future
      Queueable Apex
      Batch Apex
      Schedulable Apex
Future Method
      Annotate @future before any method it becomes the future method
      We can allow callouts by using @future(callouts=true)
      As we are annotating with @future before the method the method should follow some rules
      The method should be static and accepts void as a return type
      As it only takes void as a return type because, as it is an asynchronous method and does not
       wait for the result so if we mention any return type and if it takes time to load as this method
       does not wait for the result so to avoid this confusion future method accepts only void as
       return type
      And also, it accepts only primitive datatypes as argument because of 2 reasons one is
       serialization and other is data consistency
      As future method is made to process small types of jobs so, it can serialize or deserialize the
       primitive datatypes like Integer, String, Id and it cannot do it for non-primitive datatypes like
       Sobjects they can have reference to other objects
     And data consistency means data might not available at that time like they might be
      uncommitted or perform any dml operations which cannot handle by future method so it
      doesn’t allow non primitive datatypes
     We cannot call future method from other future method
     To avoid this draw back we can switch to Queueable apex
Syntax
     public class MyFutureClass {
              @future
              public static void myFutureMethod(String param1) {
              // Your logic here
     MyFutureClass.myFutureMethod('value');
Queueable Apex
     It is advance version of the future method which can allow primitive and non-primitive
      datatypes
     As it implements from the queueable interface it expects one abstract method that is
      execute method. This method should be called, without this method we cannot run this class
     We can monitor the jobs based on their Id and chain the jobs one after the other upto 50
      jobs that future method cannot do
     We can check status of queue jobs by using System.enqueueJobs();
     It can handle non-primitive datatypes through execute method but it is difficult to handle
      data consistency because as we perform any dml operations while running this class it can’t
      handle so avoid performing dml operations while running the class
Syntax
     public class MyQueueableClass implements Queueable {
              public void execute(QueueableContext context) {
              // Your logic here
     ID jobId = System.enqueueJob(new MyQueueableClass());
Batch Apex
     Batch apex is used to process the large number of records that can be divided into small
      batches and it would be evaluated
     As this batch class implements batchable interface so it expects three methods they are
      Start(), execute(), and finish() methods
     In start() it is used to collect the data on which batch jobs will operate which will divide the
      data into small batches. In some cases, queryLocator() method is used to operate with
      simple soql queries
     In execute() after collecting the data and divided into batches here actual processing of each
      batch is done in this method. Until batch is successfully executed it won’t execute another
      batch
     In finish() it is called after the execute method to perform any post processing operations
      such as sending an email or alerts. And we can call another batch class from this finish()
Syntax
     global class MyBatchClass implements Database.Batchable<SObject> {
               global Database.QueryLocator start(Database.BatchableContext BC) {
               return Database.getQueryLocator('SELECT Id FROM Account');
              global void execute(Database.BatchableContext BC, List<Account> scope) {
                      // Your logic here
              global void finish(Database.BatchableContext BC) {
                      // Optional logic
     ID batchId = Database.executeBatch(new MyBatchClass(), 200); // 200 = batch size
Schedulable Apex
       Schedule apex class run at specific time
       It implements schedulable interface so it expects on abstract method that is execute()
       We can schedule the jobs using System.schedule() method with a CRON expression
        String cronExp = '0 0 0 ? * MON'; // Every Monday at midnight
        String jobName = 'Weekly Data Cleanup Job';
        System.schedule(jobName, cronExp, new MySchedulerClass());
        Use ? for either Day of Week or Day of Month to avoid ambiguity.
         Positio            Field                   Example             Description
n
         1                  Seconds                 0                   0–59
         2                  Minutes                 0                   0–59
         3                  Hours                   0                   0–23
         4                  Day of Month            ?                   1–31 or ?
         5                  Month                   *                   1–12 or JAN–DEC
         6                  Day of Week             MON                 1–7 or SUN–SAT or ?
         7                  Year                    *                   Optional (empty or 2025)
Syntax
       global class MyScheduler implements Schedulable {
          global void execute(SchedulableContext SC) {
            // Your logic here
          }
        }
       String cronExp = '0 0 12 * * ?'; // Everyday at 12 PM
        String jobId = System.schedule('My Scheduled Job', cronExp, new MyScheduler());
Caller \ Callee         Future Queueable            Batch Schedulable
Future                  ❌      ❌                    ❌     ❌
Queueable               ❌      ✅ (one level only)   ❌     ✅
Batch (execute)         ❌      ✅                    ✅     ✅
Batch (start/finish)    ✅      ✅                    ✅     ✅
Schedulable             ✅      ✅                    ✅     ✅
Trigger / Synchronous   ✅      ✅                    ✅     ✅
Apex