🎓 A1Learner
🔍
0 of 30 lessons completed

Java Advanced Introduction

Java Advanced adds machinery for work that runs in parallel and for programs that inspect themselves. This lesson previews that machinery with one total built two ways.

A total built by a plain loop

A plain loop totals the list one value at a time on the main thread. The printed total is the result the rest of this lesson must match.

import java.util.List;
public class Main {
  public static void main(String[] args) {
    List<Integer> numbers = List.of(10, 20, 30, 40);
    int total = 0;
    for (int number : numbers) {
      total += number;
    }
    System.out.println("Total: " + total);
  }
}

The same total built by an executor

This program is a framed preview of the executors lesson. Three futures each return one part of the total, and the main thread adds the parts in submission order.

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
  public static void main(String[] args) throws Exception {
    ExecutorService pool = Executors.newFixedThreadPool(3);
    Future<Integer> first = pool.submit(new SumTask(List.of(10, 20)));
    Future<Integer> second = pool.submit(new SumTask(List.of(30)));
    Future<Integer> third = pool.submit(new SumTask(List.of(40)));
    int total = first.get() + second.get() + third.get();
    pool.shutdown();
    System.out.println("Total: " + total);
  }
}
class SumTask implements Callable<Integer> {
  private final List<Integer> values;
  SumTask(List<Integer> values) {
    this.values = values;
  }
  public Integer call() {
    int sum = 0;
    for (int value : values) {
      sum += value;
    }
    return sum;
  }
}

Example

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
  public static void main(String[] args) throws Exception {
    ExecutorService pool = Executors.newFixedThreadPool(2);
    Future<Integer> first = pool.submit(new SumTask(List.of(7, 13)));
    Future<Integer> second = pool.submit(new SumTask(List.of(21, 9)));
    int firstPart = first.get();
    int secondPart = second.get();
    pool.shutdown();
    System.out.println("Part: " + firstPart);
    System.out.println("Part: " + secondPart);
    System.out.println("Total: " + (firstPart + secondPart));
  }
}
class SumTask implements Callable<Integer> {
  private final List<Integer> values;
  SumTask(List<Integer> values) {
    this.values = values;
  }
  public Integer call() {
    int sum = 0;
    for (int value : values) {
      sum += value;
    }
    return sum;
  }
}

Key points

  • Concurrency comes first, with threads, executors, and guarded shared data.
  • Reflection and annotations let a program read its own classes at runtime.
  • Generics internals show the bridge methods and the risks behind erased types.
  • Sealed types and patterns close a family of types and match its members.
  • Optional and streams at depth add flat mapping, custom collectors, and parallel work.
  • Nested classes, networking and NIO, serialization, modules, and the JVM close the course.

In this example, two tasks each total one part of the list on pool threads. The main thread reads the futures in submission order, prints both parts, and prints their combined total.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What stays the same when the total moves from a plain loop to an executor in this lesson?