Copy cat > /tmp/AdvLab11.java << 'JAVAEOF'
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;
import java.util.*;
public class AdvLab11 {
// Semaphore-bounded connection pool
static class ConnectionPool {
private final Semaphore semaphore;
private final ConcurrentLinkedQueue<String> connections = new ConcurrentLinkedQueue<>();
ConnectionPool(int maxSize) {
semaphore = new Semaphore(maxSize, true); // fair = FIFO order
for (int i = 0; i < maxSize; i++) connections.offer("conn-" + i);
}
String acquire() throws InterruptedException { semaphore.acquire(); return connections.poll(); }
void release(String conn) { connections.offer(conn); semaphore.release(); }
int available() { return semaphore.availablePermits(); }
}
// ReadWriteLock cache
static class PriceCache {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Map<Integer,Double> cache = new HashMap<>();
private final AtomicInteger reads = new AtomicInteger(), writes = new AtomicInteger();
void update(int id, double price) {
rwLock.writeLock().lock();
try { cache.put(id, price); writes.incrementAndGet(); }
finally { rwLock.writeLock().unlock(); }
}
Optional<Double> get(int id) {
rwLock.readLock().lock();
try { reads.incrementAndGet(); return Optional.ofNullable(cache.get(id)); }
finally { rwLock.readLock().unlock(); }
}
void stats() { System.out.printf(" Cache: reads=%d writes=%d entries=%d%n",
reads.get(), writes.get(), cache.size()); }
}
public static void main(String[] args) throws Exception {
var executor = Executors.newVirtualThreadPerTaskExecutor();
// Step 1: Semaphore connection pool
System.out.println("=== Semaphore Connection Pool (max=3) ===");
var pool = new ConnectionPool(3);
System.out.println(" Available: " + pool.available());
var poolFutures = new ArrayList<Future<String>>();
for (int i = 0; i < 6; i++) {
poolFutures.add(executor.submit(() -> {
String conn = pool.acquire();
try { Thread.sleep(30); return conn + " used"; }
finally { pool.release(conn); }
}));
}
var poolResults = poolFutures.stream()
.map(f -> { try { return f.get(); } catch (Exception e) { return "err"; } })
.sorted().toList();
poolResults.forEach(r -> System.out.println(" " + r));
System.out.println(" Available after: " + pool.available());
// Step 2: ReadWriteLock
System.out.println("\n=== ReadWriteLock Price Cache ===");
var cache = new PriceCache();
cache.update(1, 864.0); cache.update(2, 49.99); cache.update(3, 99.99);
var rwFutures = new ArrayList<Future<?>>();
for (int i = 0; i < 20; i++) { // 20 readers
final int id = (i % 3) + 1;
rwFutures.add(executor.submit(() -> cache.get(id)));
}
rwFutures.add(executor.submit(() -> { cache.update(1, 820.0); return null; })); // 1 writer
for (var f : rwFutures) f.get();
cache.stats();
System.out.println(" Surface Pro current price: $" + cache.get(1).orElse(0.0));
// Step 3: BlockingQueue producer-consumer
System.out.println("\n=== BlockingQueue Producer-Consumer ===");
var queue = new LinkedBlockingQueue<Integer>(10);
var produced = new AtomicInteger(), consumed = new AtomicInteger();
var doneLatch = new CountDownLatch(2);
executor.submit(() -> {
try {
for (int i = 1; i <= 10; i++) { queue.put(i); produced.incrementAndGet(); Thread.sleep(5); }
} catch (InterruptedException e) {}
finally { doneLatch.countDown(); }
});
executor.submit(() -> {
try {
for (int i = 0; i < 10; i++) { queue.take(); consumed.incrementAndGet(); }
} catch (InterruptedException e) {}
finally { doneLatch.countDown(); }
});
doneLatch.await(3, TimeUnit.SECONDS);
System.out.printf(" Produced: %d Consumed: %d%n", produced.get(), consumed.get());
// Step 4: Phaser multi-phase (3 workers, 2 phases)
System.out.println("\n=== Phaser: Multi-phase Barrier ===");
var phaseLog = new CopyOnWriteArrayList<String>();
var phase1Latch = new CountDownLatch(3);
var phase2Latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
final int id = i;
executor.submit(() -> {
try {
Thread.sleep(10 + id * 5);
phaseLog.add("Phase1-p" + id);
phase1Latch.countDown();
phase1Latch.await(1, TimeUnit.SECONDS); // wait for all phase1
Thread.sleep(5);
phaseLog.add("Phase2-p" + id);
phase2Latch.countDown();
} catch (Exception e) { phase1Latch.countDown(); phase2Latch.countDown(); }
});
}
phase2Latch.await(2, TimeUnit.SECONDS);
executor.shutdown();
executor.awaitTermination(3, TimeUnit.SECONDS);
long p1 = phaseLog.stream().filter(s->s.startsWith("Phase1")).count();
long p2 = phaseLog.stream().filter(s->s.startsWith("Phase2")).count();
System.out.printf(" Phase1=%d/3 Phase2=%d/3%n", p1, p2);
System.out.println(" Order: " + phaseLog.stream().sorted().toList());
// Step 5: Atomic operations
System.out.println("\n=== Atomic Operations ===");
var counter = new AtomicLong(0);
var ex2 = Executors.newVirtualThreadPerTaskExecutor();
var atomicFutures = new ArrayList<Future<?>>();
for (int i = 0; i < 1000; i++) {
atomicFutures.add(ex2.submit(() -> counter.incrementAndGet()));
}
for (var f : atomicFutures) f.get();
ex2.shutdown();
System.out.println(" AtomicLong after 1000 increments: " + counter.get() + " (expected 1000)");
}
}
JAVAEOF
docker run --rm -v /tmp/AdvLab11.java:/tmp/AdvLab11.java zchencow/innozverse-java:latest sh -c "javac /tmp/AdvLab11.java -d /tmp && java -cp /tmp AdvLab11"