MS Lesson26: Threads
1. Process - emeliyyat sistemi terefinden ishe salinan, oz ayrica yaddash sahesine malik olan programin icra nusxesidir.
Mes biz kompumuzda muxtelif programlar acanda Paint, Excel ve s. bunlar ferqli proseslerdir.
OS her bir prosese ferqli registerler, stack memory, heap memory assign edir.
Restoran misali:
Restoran = process
Bina = yaddash (RAM)
Ishciler = thread
Yeni process ishe salinmish bir programdir.
* Her proses oz yaddashinda ishleyir, bashqasina toxuna bilmez.
* OS her prosese unikal ID verir.
* Yaratmaq / silmek bahalidir.
* Biri crash olsa, digerine tesir etmir.
Bir prosesin icinde coxlu thread ola biler. Amma bir thread yalniz bir prosese aid ola biler.
Java kodu bashlayanda JVM ozu de bir nece thread yaradir:
* main thread - bizim kodumuz
* GC thread - Garbage Collector
* Finalizer thread
* Signal Dispatcher thread
2. Thread - process icinde ishleyen ayrica ish axinidir. Kodun setir setir icra olundugu yoldur.
Restoran - process
Ashpaz 1 - pizza bishirir - thread1
Ashpaz 2 - salat hazirlayir - thread2
Ashpaz 3 - desert duzeldir - thread3
Hami eyni anda ishleyir - paralel.
Hami eyni metbexte ishelyir - eyni yaddash.
3. Time Slicing
CPU - tekce beyin deyil, milyardlarla tranzistordan ibaret cipdir. Tranzistor elektrik kecirik ya kecirmir 0 ve 1.
Core - CPU-nun icinde musteqil bir ishcidir. Ona kod verirsen o da icra edir, bashqa hecne bilmir.
CPU - fabrika, Core - fabrikadaki ishci.
Core-un icinde 4 esas sahe var:
1. Fetch unit: "Novbeti emri getir"
RAM-da bizim Java kodumuz durur:
Unvan 100: int a = 5;
Unvan 104: int b = 3;
Unvan 108: int c = a + b;
Fetch unit:
"Unvan 100 get -> Decode ver"
"Unvan 104 get -> Decode var"
...
Problemi: RAM yavashdir, 70 nanosaniye gozlemek lazimdir, Core ise 0.3 nanosaniyede ishleyir. Yeni Core RAM-dan 200x daha suretlidir. Buna gore Core-un daxilinde oz cache-i var.
2. Decode unit: "Bu emr ne demekdir?"
Tercumeci, genen emri CPU diline cevirir.
Sən yazırsan:
int c = a + b;
JVM çevirir (Bytecode):
iload_1 ← a-nı yüklə
iload_2 ← b-ni yüklə
iadd ← topla
istore_3 ← c-yə yaz
CPU görür (Machine Code):
10110000 00000101
10110011 00000011
00000001 11000011
Decode unit bunlari oxuyur ve deyir:
"A-nı Register-ə yüklə"
"B-ni Register-ə yüklə"
"İkisini ALU-da topla"
"Nəticəni Register-ə yaz"
3. ALU: "Hesablama et"
Arithmetic Logic Unit - butun hesablama burada gedir.
4. Register: "Neticeni saxla"
Yaddaş növləri sürətə görə:
Register │██████████████████████│ 0.3 ns ← Core-un içi
L1 Cache │████████████████ │ 1 ns
L2 Cache │████████ │ 5 ns
L3 Cache │████ │ 15 ns
RAM │█ │ 70 ns ← 200x yavaş!
SSD │ │ 100 µs
HDD │ │ 10 ms
Core-da cəmi ~16 Register var Hər biri 64 bit = 8 byte saxlayır
Bir core eyni anda yalniz 1 ish gore biler. Amma ele suretli novbe ile kecir ki, sanki hamisini eyni anda icra edir.
package az.etibarli;
class Runner1 {
public void execute() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner1: " + i);
}
}
}
class Runner2 {
public void execute() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner2: " + i);
}
}
}
public class Main {
static void main() {
Runner1 runner1 = new Runner1();
Runner2 runner2 = new Runner2();
runner1.execute();
runner2.execute();
}
}
package az.etibarli;
class Runner1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner1: " + i);
}
}
}
class Runner2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner2: " + i);
}
}
}
public class Main {
static void main() {
Thread thread1 = new Thread(new Runner1());
Thread thread2 = new Thread(new Runner2());
thread1.start();
thread2.start();
}
}
package az.etibarli;
class Runner1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner1: " + i);
}
}
}
class Runner2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner2: " + i);
}
}
}
public class Main {
static void main() throws InterruptedException {
System.out.println("Start");
Thread thread1 = new Thread(new Runner1());
Thread thread2 = new Thread(new Runner2());
thread1.start();
thread2.start();
thread1.join();
System.out.println("Finish");
}
}
package az.etibarli;
class Runner1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner1: " + i);
}
}
}
class Runner2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Runner2: " + i);
}
}
}
public class Main {
static void main() throws InterruptedException {
System.out.println("Start");
Thread thread1 = new Thread(new Runner1());
Thread thread2 = new Thread(new Runner2());
thread1.start();
thread2.start();
thread1.join();
System.out.println("Finish");
}
}
package az.etibarli;
public class Main {
static long heavyWork() {
long result = 0;
for (long i = 0; i < 1_000_000_000L; i++) {
result += i;
}
return result;
}
static void main() throws InterruptedException {
System.out.println("=== 1 Thread ===");
long start1 = System.currentTimeMillis();
heavyWork();
heavyWork();
long end1 = System.currentTimeMillis();
System.out.println("1 Thread time: " +
(end1 - start1) + "ms");
System.out.println("\n=== 2 Thread ===");
long start2 = System.currentTimeMillis();
Thread t1 = new Thread(() -> heavyWork());
Thread t2 = new Thread(() -> heavyWork());
t1.start();
t2.start();
t1.join();
t2.join();
long end2 = System.currentTimeMillis();
System.out.println("2 Thread time: " +
(end2 - start2) + "ms");
}
}
package az.etibarli;
class Runner1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Runner1: " + i);
}
}
}
class Runner2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Runner2: " + i);
}
}
}
public class Main {
static void main() throws InterruptedException {
System.out.println("Start");
Thread thread1 = new Thread(new Runner1());
Thread thread2 = new Thread(new Runner2());
thread1.start();
thread2.start();
// list of threads in JVM
for (Thread t : Thread.getAllStackTraces().keySet()) {
System.out.println("Thread name: " + t.getName() + ", State: " + t.getState());
}
thread1.join();
System.out.println("Finish");
}
}
package az.etibarli;
class NormalWorker implements Runnable {
public void run() {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Executing the normal thread...");
}
}
class DaemonWorker implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Executing the daemon thread...");
}
}
}
public class Main {
static void main() throws InterruptedException {
System.out.println("Started...");
Thread t1 = new Thread(new NormalWorker());
Thread t2 = new Thread(new DaemonWorker());
t2.setDaemon(true);
t1.start();
t2.start();
System.out.println("Finished...");
}
}
* Daemon Thread - background thread support user thread. JVM does not wait for daemon threads. Must explicitly set using setDaemon(true). Can also have any priority, but usually lower. Acts as background service threads.
package az.etibarli;
class Task implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " count: " + i);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class Main {
static void main() throws InterruptedException {
System.out.println("Started...");
Thread low = new Thread(new Task(), "Low priority thread");
Thread medium = new Thread(new Task(), "Medium priority thread");
Thread high = new Thread(new Task(), "High priority thread");
low.setPriority(Thread.MIN_PRIORITY);
medium.setPriority(Thread.NORM_PRIORITY);
high.setPriority(Thread.MAX_PRIORITY);
low.start();
medium.start();
high.start();
System.out.println("Finished...");
}
}
package az.etibarli;
public class SynchronizationExample {
private static int counter = 0;
public static void increment() {
counter++;
}
static void main() throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter value is : " + counter);
}
}
package az.etibarli;
public class SynchronizationExample {
private static int counter = 0;
public synchronized static void increment() {
counter++;
}
static void main() throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter value is : " + counter);
}
}
package az.etibarli;
public class SynchronizationExample {
private static int counter1 = 0;
private static int counter2 = 0;
public synchronized static void increment1() {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
counter1++;
}
public synchronized static void increment2() {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
counter2++;
}
static void main() throws InterruptedException {
long start = System.currentTimeMillis();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment1();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
increment2();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("Counter value is : " + counter1);
System.out.println("Counter value is : " + counter2);
System.out.println("Time elapsed: " + (end - start));
}
}
package az.etibarli;
public class SynchronizationExample {
private static int counter1 = 0;
private static int counter2 = 0;
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
public synchronized static void increment1() {
// t1, t2
// synchronized (lock1) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
counter1++;
// }
// synchronized (lock2) {
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
counter2++;
// }
}
static void main() throws InterruptedException {
long start = System.currentTimeMillis();
Thread t1 = new Thread(() -> {
// for (int i = 0; i < 5000; i++) {
increment1();
// }
});
Thread t2 = new Thread(() -> {
// for (int i = 0; i < 5000; i++) {
increment1();
// }
});
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("Counter value is : " + counter1);
System.out.println("Counter value is : " + counter2);
System.out.println("Time elapsed: " + (end - start));
}
}
package az.etibarli;
class ObjectLocking {
public synchronized void instanceMethod() {
System.out.println(Thread.currentThread().getName() + " started instance method...");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " finished instance method...");
}
}
public class Main {
static void main() throws InterruptedException {
long start = System.currentTimeMillis();
ObjectLocking obj1 = new ObjectLocking();
ObjectLocking obj2 = new ObjectLocking();
Runnable task1 = obj1::instanceMethod;
Runnable task2 = obj1::instanceMethod;
Thread t1 = new Thread(task1, "First Thread");
Thread t2 = new Thread(task2, "Second Thread");
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("Time elapsed: " + (end - start));
}
}
package az.etibarli;
class ObjectLocking {
public static synchronized void instanceMethod() {
System.out.println(Thread.currentThread().getName() + " started instance method...");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " finished instance method...");
}
}
public class Main {
static void main() throws InterruptedException {
long start = System.currentTimeMillis();
Runnable task1 = ObjectLocking::instanceMethod;
Runnable task2 = ObjectLocking::instanceMethod;
Thread t1 = new Thread(task1, "First Thread");
Thread t2 = new Thread(task2, "Second Thread");
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("Time elapsed: " + (end - start));
}
}
package az.etibarli;
class Process {
public void produce() throws Exception {
synchronized (this) {
System.out.println("Running the produce method...");
wait();
System.out.println("Again in the produce method...");
}
}
public void consume() throws Exception {
Thread.sleep(4000);
synchronized (this) {
System.out.println("Running the consume method...");
notify();
System.out.println("After the notify() method call in the consume method...");
}
}
}
public class Main {
static void main() throws InterruptedException {
long start = System.currentTimeMillis();
Process process = new Process();
Thread t1 = new Thread(() -> {
try {
process.produce();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(() -> {
try {
process.consume();
} catch (Exception e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
long end = System.currentTimeMillis();
// System.out.println("Time elapsed: " + (end - start));
}
}
Let's discuss the difference between sleep and wait. They may seem to be very similar but there are fundamental differences between them.
you call
waiton the Object while on the other hand you callsleepon the Thread itselfwait can be interrupter (this is why we need the InterruptedException) while on the other hand sleep can not
wait(andnotify) must happen in asynchronizedblock on the monitor object whereassleepdoes notsleepoperation does not release the locks it holds while on the other handwaitreleases the lock on the object thatwait()is called on
package az.etibarli;
import java.util.LinkedList;
import java.util.List;
class SharedBuffer {
private List<Integer> buffer = new LinkedList<>();
private int capacity = 5;
public synchronized void produce() throws Exception {
if (buffer.size() == capacity) {
System.out.println("Buffer is full, produce waiting...");
wait();
}
System.out.println("Adding items with the producer...");
for (int i = 0; i < capacity; i++) {
buffer.add(i);
System.out.println("Added value: " + i);
}
// wake up the consumer
notify();
}
public synchronized void consume() throws Exception {
if (buffer.size() < capacity) {
System.out.println("Buffer not fully yet, consumer waiting...");
wait();
}
while (!buffer.isEmpty()) {
int item = buffer.remove(0);
System.out.println("Consumer removes: " + item);
Thread.sleep(300);
}
// wake up the producer
notify();
}
}
class Consumer implements Runnable {
private SharedBuffer sharedBuffer;
public Consumer(SharedBuffer sharedBuffer) {
this.sharedBuffer = sharedBuffer;
}
@Override
public void run() {
while (true) {
try {
this.sharedBuffer.consume();
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class Producer implements Runnable {
private SharedBuffer sharedBuffer;
public Producer(SharedBuffer sharedBuffer) {
this.sharedBuffer = sharedBuffer;
}
@Override
public void run() {
while (true) {
try {
this.sharedBuffer.produce();
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class Main {
static void main() throws InterruptedException {
SharedBuffer buffer = new SharedBuffer();
Thread t1 = new Thread(new Producer(buffer));
Thread t2 = new Thread(new Consumer(buffer));
t1.start();
t2.start();
}
}
package az.etibarli;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DeadLock {
private Lock lock1 = new ReentrantLock(true);
private Lock lock2 = new ReentrantLock(true);
static void main() {
DeadLock deadLock = new DeadLock();
new Thread(deadLock::worker1, "worker1").start();
new Thread(deadLock::worker2, "worker2").start();
}
public void worker1() {
lock1.lock();
System.out.println("Worker 1 acquires the lock1...");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock2.lock();
System.out.println("Worker 1 acquires the lock2...");
lock1.unlock();
lock2.unlock();
}
public void worker2() {
lock2.lock();
System.out.println("Worker 2 acquires the lock2...");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock1.lock();
System.out.println("Worker 2 acquires the lock1...");
lock2.unlock();
lock1.unlock();
}
}
package az.etibarli;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main3 {
private Lock lock1 = new ReentrantLock(true);
private Lock lock2 = new ReentrantLock(true);
static void main() {
Main3 main3 = new Main3();
new Thread(main3::worker1, "worker1").start();
new Thread(main3::worker2, "worker2").start();
}
public void worker1() {
while (true) {
try {
lock1.tryLock(50, TimeUnit.MILLISECONDS);
System.out.println("worker1 acquires the lock1...");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("worker1 tries to get lock2...");
if (lock2.tryLock()) {
System.out.println("worker1 acquires the lock2...");
lock2.unlock();
} else {
System.out.println("worker1 can not acquire lock2...");
continue;
}
break;
}
lock1.unlock();
lock2.unlock();
}
public void worker2() {
while (true) {
try {
lock2.tryLock(50, TimeUnit.MILLISECONDS);
System.out.println("worker2 acquires the lock2...");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("worker2 tries to get lock1...");
if (lock1.tryLock()) {
System.out.println("worker2 acquires the lock1...");
lock1.unlock();
} else {
System.out.println("worker2 can not acquire lock1...");
continue;
}
break;
}
lock1.unlock();
lock2.unlock();
}
}
package az.etibarli;
public class WithoutVolatile {
// volatile YOX!
private static boolean running = true;
public static void main(String[] args) throws Exception {
Thread worker = new Thread(() -> {
int count = 0;
while (running) { // ← running-i Cache-dən oxuyur!
count++;
}
System.out.println("Worker dayandı! Count: " + count);
});
worker.start();
Thread.sleep(2000); // 2 saniyə gözlə
System.out.println("running = false edirik...");
running = false; // ← Main thread Cache-inə yazdı
// Worker thread GÖRMÜR!
Thread.sleep(2000); // daha 2 saniyə gözlə
System.out.println("Main bitdi!");
// Worker hələ işləyir! ❌
}
}
package az.etibarli;
public class WithVolatile {
// volatile VAR!
private static volatile boolean running = true;
public static void main(String[] args) throws Exception {
Thread worker = new Thread(() -> {
int count = 0;
while (running) { // ← running-i RAM-dan oxuyur!
count++;
}
System.out.println("Worker dayandı! Count: " + count);
});
worker.start();
Thread.sleep(2000); // 2 saniyə gözlə
System.out.println("running = false edirik...");
running = false; // ← BİRBAŞA RAM-a yazdı!
// Worker dərhal GÖRÜR! ✅
Thread.sleep(2000);
System.out.println("Main bitdi!");
}
}
package az.etibarli;
class WithoutVolatile extends Thread {
private boolean running = true;
@Override
public void run() {
long count = 0;
while (running) {
// System.out.println("t1 here");
count++;
}
System.out.println("WithoutVolatile dayandı! Count: " + count);
}
public void cancel() {
running = false;
}
}
class WithVolatile extends Thread {
private volatile boolean running = true;
@Override
public void run() {
long count = 0;
while (running) {
// System.out.println("t2 here");
count++;
}
System.out.println("WithVolatile dayandı! Count: " + count);
}
public void cancel() {
running = false;
}
}
public class VolatileDemo {
static void main() throws Exception {
WithVolatile t1 = new WithVolatile();
WithoutVolatile t2 = new WithoutVolatile();
t1.start();
t2.start();
Thread.sleep(2000); // ← JIT-in cache-ləməsi üçün vaxt veririk
t1.cancel();
t2.cancel();
Thread.sleep(1000);
System.out.println("t1 (volatile) hələ işləyir? " + t1.isAlive());
System.out.println("t2 (no volatile) hələ işləyir? " + t2.isAlive());
}
}
package az.etibarli;
class WithoutVolatile extends Thread {
private boolean running = true;
@Override
public void run() {
long count = 0;
while (running) {
System.out.println("t1 here");
count++;
}
System.out.println("WithoutVolatile dayandı! Count: " + count);
}
public void cancel() {
running = false;
}
}
class WithVolatile extends Thread {
private volatile boolean running = true;
@Override
public void run() {
long count = 0;
while (running) {
System.out.println("t2 here");
count++;
}
System.out.println("WithVolatile dayandı! Count: " + count);
}
public void cancel() {
running = false;
}
}
public class VolatileDemo {
static void main() throws Exception {
WithVolatile t1 = new WithVolatile();
WithoutVolatile t2 = new WithoutVolatile();
t1.start();
t2.start();
Thread.sleep(2000); // ← JIT-in cache-ləməsi üçün vaxt veririk
t1.cancel();
t2.cancel();
Thread.sleep(1000);
System.out.println("t1 (volatile) hələ işləyir? " + t1.isAlive());
System.out.println("t2 (no volatile) hələ işləyir? " + t2.isAlive());
}
}
package az.etibarli;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
class Kitchen {
LinkedList<String> meals = new LinkedList<>();
private final int capacity = 8;
public synchronized void addMeal(String chef, String meal) throws Exception {
if (meals.size() == capacity) {
System.out.println("Kitchen is full, " + chef + " is waiting...");
wait();
}
meals.add(meal);
System.out.println(chef + " prepared meal: " + meal);
notify();
}
public synchronized void takeMeal(String waiter) throws Exception {
if (meals.isEmpty()) {
System.out.println("Meal is not ready yet, " + waiter + " is waiting...");
wait();
}
String meal = meals.remove(0);
System.out.println(waiter + " is taking " + meal);
notify();
}
}
class Chef implements Runnable {
private String name;
private Kitchen kitchen;
private List<String> meals = Arrays.asList("Pizza", "Burger", "Pasta", "Sushi", "Salad", "Soup", "Steak", "Kebab");
public Chef(String name, Kitchen kitchen) {
this.name = name;
this.kitchen = kitchen;
}
@Override
public void run() {
Random random = new Random();
try {
while (true) {
String meal = meals.get(random.nextInt(meals.size()));
System.out.println(name + " is preparing " + meal);
Thread.sleep(5000); // ← lock xaricində, Waiter bloklanmır
this.kitchen.addMeal(name, meal);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Waiter implements Runnable {
private String name;
private Kitchen kitchen;
public Waiter(String name, Kitchen kitchen) {
this.name = name;
this.kitchen = kitchen;
}
@Override
public void run() {
try {
while (true) {
this.kitchen.takeMeal(name);
Thread.sleep(2000); // ← lock xaricində
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Task1 {
static void main() {
Kitchen kitchen = new Kitchen();
Chef ali = new Chef("Ali", kitchen);
Waiter nizam = new Waiter("Nizam", kitchen);
Thread t1 = new Thread(ali);
Thread t2 = new Thread(nizam);
t1.start();
t2.start();
}
}
package az.etibarli;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
class Kitchen {
private LinkedList<String> meals = new LinkedList<>();
private final int capacity = 8;
public synchronized void addMeal(String chef, String meal) throws Exception {
while (meals.size() == capacity) {
System.out.println("Kitchen is full, " + chef + " is waiting...");
wait();
}
meals.add(meal);
System.out.println(chef + " prepared meal: " + meal);
notifyAll();
}
public synchronized void takeMeal(String waiter) throws Exception {
while (meals.isEmpty()) {
System.out.println("Meal is not ready yet, " + waiter + " is waiting...");
wait();
}
String meal = meals.remove(0);
System.out.println(waiter + " is taking " + meal);
notifyAll();
}
}
class Chef implements Runnable {
private String name;
private Kitchen kitchen;
private List<String> meals = Arrays.asList("Pizza", "Burger", "Pasta", "Sushi", "Salad", "Soup", "Steak", "Kebab");
public Chef(String name, Kitchen kitchen) {
this.name = name;
this.kitchen = kitchen;
}
@Override
public void run() {
Random random = new Random();
try {
while (true) {
String meal = meals.get(random.nextInt(meals.size()));
System.out.println(name + " is preparing " + meal);
Thread.sleep(5000); // ← lock xaricində, Waiter bloklanmır
this.kitchen.addMeal(name, meal);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Waiter implements Runnable {
private String name;
private Kitchen kitchen;
public Waiter(String name, Kitchen kitchen) {
this.name = name;
this.kitchen = kitchen;
}
@Override
public void run() {
try {
while (true) {
this.kitchen.takeMeal(name);
Thread.sleep(2000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Task1 {
static void main() {
Kitchen kitchen = new Kitchen();
Chef ali = new Chef("Ali", kitchen);
Chef murad = new Chef("Murad", kitchen);
Waiter nizam = new Waiter("Nizam", kitchen);
Waiter seymur = new Waiter("Seymur", kitchen);
Thread t1 = new Thread(ali);
Thread t2 = new Thread(murad);
Thread t3 = new Thread(nizam);
Thread t4 = new Thread(seymur);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
Ashagidaki kod parcasi yuxarida deyilenleri tesdiq edir:
package az.etibarli;
class Test {
public synchronized void method1() throws Exception {
System.out.println("start method1");
Thread.sleep(3000);
wait();
System.out.println("finish method1");
notify();
}
public synchronized void method2() throws Exception {
System.out.println("start method2");
Thread.sleep(2000);
notify();
Thread.sleep(10000);
System.out.println("finish method2");
}
}
public class Task3 {
static void main() {
Test test = new Test();
Thread t1 = new Thread(() -> {
try {
test.method1();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
Thread t2 = new Thread(() -> {
try {
test.method2();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
t1.start();
t2.start();
}
}
package az.etibarli;
class MissedSignalDemo {
public void waiter() throws Exception {
System.out.println("start waiter");
Thread.sleep(2000);
synchronized (this) {
System.out.println("waiter going to wait");
wait();
}
System.out.println("finish waiter");
}
public void notifier() throws Exception {
Thread.sleep(500);
System.out.println("notifier started");
synchronized (this) {
System.out.println("notifier going to nitify");
notify();
}
System.out.println("notifier finished");
}
}
public class Task4 {
static void main() {
MissedSignalDemo demo = new MissedSignalDemo();
Thread t1 = new Thread(() -> {
try {
demo.waiter();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
Thread t2 = new Thread(() -> {
try {
demo.notifier();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
t1.start();
t2.start();
}
}
package az.etibarli;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Task5 {
private static Lock lock = new ReentrantLock(true);
private static Condition condition = lock.newCondition();
public static void produce() throws Exception {
lock.lock();
System.out.println("start produce...");
Thread.sleep(2000);
condition.await();
System.out.println("finish produce...");
}
public static void consume() throws Exception {
Thread.sleep(1000);
lock.lock();
System.out.println("start consume...");
Thread.sleep(2000);
condition.signal();
System.out.println("finish consume...");
}
static void main() throws Exception {
Thread t1 = new Thread(() -> {
while (true) {
try {
produce();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
try {
consume();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t2.start();
}
}
package az.etibarli.Lesson9;
class Task {
private int turn = 1; // 1=fetch, 3=save, 2=process
public void fetch() throws Exception {
synchronized (this) {
while (turn != 1)
wait();
System.out.println("Datani yukleyirem...");
Thread.sleep(2000);
System.out.println("Data hazirdir");
turn = 3; // ← T3 (save) növbəsi!
notifyAll();
}
}
public void process() throws Exception {
synchronized (this) {
while (turn != 2) // ← turn 2 olana qədər gözlə!
wait();
System.out.println("Datani emal edirem...");
Thread.sleep(3000);
System.out.println("Emal bitdi");
}
}
public void save() throws Exception {
synchronized (this) {
while (turn != 3) // ← turn 3 olana qədər gözlə!
wait();
System.out.println("Datani saxlayiram...");
Thread.sleep(1000);
System.out.println("Saxlandi");
turn = 2; // ← T2 (process) növbəsi!
notifyAll();
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
Task task = new Task();
Thread t1 = new Thread(() -> {
try {
task.fetch();
} catch (Exception e) {
throw new RuntimeException(e);
}
}, "T1-fetch");
Thread t2 = new Thread(() -> {
try {
task.process();
} catch (Exception e) {
throw new RuntimeException(e);
}
}, "T2-process");
Thread t3 = new Thread(() -> {
try {
task.save();
} catch (Exception e) {
throw new RuntimeException(e);
}
}, "T3-save");
t2.start(); // process əvvəl → wait()-ə girsin
Thread.sleep(100);
t3.start(); // save sonra → wait()-ə girsin
Thread.sleep(100);
t1.start(); // fetch ən son → işləsin
t1.join();
t2.join();
t3.join();
}
}
package az.etibarli.lesson11;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
class SharedOven {
private final List<String> list = new LinkedList<>();
private final int capacity = 3;
private final AtomicInteger count = new AtomicInteger(1);
public void produce(Baker baker) throws Exception {
// Bişirmə xaricidə — Lock tutmur!
System.out.println(baker.getName() + " is baking...");
Thread.sleep(baker.getBakingTime());
synchronized (this) {
while (list.size() == capacity) {
System.out.println("Oven is full, " +
baker.getName() + " is waiting...");
wait();
}
String bread = baker.getName() + "-bread-" +
count.getAndIncrement();
list.add(bread);
System.out.println(baker.getName() +
" baked! Oven: " + list.size() + "/" + capacity);
notifyAll();
}
}
public void consume(Customer customer) throws Exception {
String item;
synchronized (this) {
while (list.isEmpty()) {
System.out.println("Oven is empty, " +
customer.getName() + " is waiting...");
wait();
}
item = list.remove(0);
System.out.println(customer.getName() +
" took: " + item +
" | Oven: " + list.size() + "/" + capacity);
notifyAll();
}
// Yemək xaricidə — Lock tutmur!
Thread.sleep(customer.getTakingTime());
}
}
class Baker implements Runnable {
private final SharedOven oven;
private final String name;
private final int bakingTime;
public Baker(SharedOven oven, String name, int bakingTime) {
this.oven = oven;
this.name = name;
this.bakingTime = bakingTime;
}
public String getName() {
return name;
}
public int getBakingTime() {
return bakingTime;
}
@Override
public void run() {
try {
while (true) {
oven.produce(this);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Customer implements Runnable {
private final SharedOven oven;
private final String name;
private final int takingTime;
public Customer(SharedOven oven, String name, int takingTime) {
this.oven = oven;
this.name = name;
this.takingTime = takingTime;
}
public String getName() {
return name;
}
public int getTakingTime() {
return takingTime;
}
@Override
public void run() {
try {
while (true) {
oven.consume(this);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
SharedOven oven = new SharedOven();
Thread t1 = new Thread(new Baker(oven, "Ali", 2000));
Thread t2 = new Thread(new Baker(oven, "Aykhan", 3000));
Thread t3 = new Thread(new Customer(oven, "Parvin", 4000));
Thread t4 = new Thread(new Customer(oven, "Narmin", 4000));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
package az.etibarli;
import java.util.concurrent.Semaphore;
public class DatabasePool {
private Semaphore semaphore = new Semaphore(2); // 3 bağlantı
public void query(String threadName) throws Exception {
System.out.println(threadName + " bağlantı gözləyir...");
semaphore.acquire(); // ← bağlantı al
try {
System.out.println(threadName + " bağlantı aldı!");
Thread.sleep(5000); // ← sorğu icra olunur
System.out.println(threadName + " bitdi.");
} finally {
semaphore.release(); // ← bağlantını burax
}
}
}
package az.etibarli;
public class Main4 {
static void main() {
DatabasePool pool = new DatabasePool();
for (int i = 1; i <= 7; i++) {
String name = "Thread-" + i;
new Thread(() -> {
try {
pool.query(name);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
Xülasə:
| Lock | Binary Semaphore | Counting Semaphore | |
|---|---|---|---|
| Eyni anda neçə thread | 1 | 1 | N |
| Kim buraxır | Yalnız alan | İstənilən thread | İstənilən thread |
| İstifadə | Kritik hissə | Mutex | Resurs pool |
package az.etibarli;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Task implements Runnable {
private int id;
public Task(int id) {
this.id = id;
}
@Override
public void run() {
System.out.println("Task with id " + id + " is in work - thread id: " + Thread.currentThread().getName());
long duration = (long) (Math.random() * 5);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class SingleThreadExecutor {
static void main() {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
executor.execute(new Task(i));
}
}
}
package az.etibarli;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class Task6 {
static void main() throws Exception {
long start = System.currentTimeMillis();
ExecutorService service = Executors.newFixedThreadPool(3);
List<Future<String>> futures = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
int customerId = i;
futures.add(service.submit(() -> checkBalance(customerId)));
}
String maxResult = null;
int maxBalance = Integer.MIN_VALUE;
for (Future<String> future : futures) {
try {
String result = future.get(4, TimeUnit.SECONDS);
System.out.println(result);
// Balansı çıxart və müqayisə et
int balance = extractBalance(result);
if (balance > maxBalance) {
maxBalance = balance;
maxResult = result;
}
} catch (Exception e) {
System.out.println("⏰ Timeout! Müştəri cavab vermədi!");
future.cancel(true);
}
}
System.out.println("\n🏆 Ən yüksək balans: " + maxResult);
service.shutdown();
boolean finished = service.awaitTermination(4, TimeUnit.SECONDS);
if (!finished) {
System.out.println("⚠️ Timeout! Zorla dayandırılır...");
service.shutdownNow();
}
System.out.println("Ümumi vaxt: " +
(System.currentTimeMillis() - start) + "ms");
}
static String checkBalance(int customerId)
throws InterruptedException {
Random random = new Random();
int balance = random.nextInt(10000) + 500;
Thread.sleep(customerId * 1000);
return "Müştəri-" + customerId +
" balansı: " + balance + " AZN";
}
static int extractBalance(String result) {
String[] parts = result.split(" ");
return Integer.parseInt(parts[parts.length - 2]);
}
}
package az.etibarli;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
ExecutorService service = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 3; i++) {
int finalI = i;
service.submit(() -> {
try {
System.out.println("Thread started..." + Thread.currentThread().getName());
System.out.println("Thread is working..." + Thread.currentThread().getName());
Thread.sleep(10000 * finalI);
System.out.println("Thread finished..." + Thread.currentThread().getName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
latch.countDown();
}
});
}
latch.await();
service.shutdown();
System.out.println("Everything is done");
}
}
package az.etibarli;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Oca {
public static void main(String[] args) throws Exception {
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("=== HAMISI ÇATDI! DAVAM! ===")
);
ExecutorService service = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 3; i++) {
int finalI = i;
service.submit(() -> {
try {
System.out.println("Thread-" + finalI +
" başladı → " + finalI + "s işləyəcək");
Thread.sleep(finalI * 1000); // 1s, 2s, 3s
System.out.println("Thread-" + finalI +
" bitdi → barrier-i gözləyir... 😴");
barrier.await();
System.out.println("Thread-" + finalI +
" davam etdi! 🚀");
} catch (InterruptedException |
BrokenBarrierException e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
}
package az.etibarli;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Oca {
public static void main(String[] args) throws Exception {
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("=== Merhele tamamlandi! ===")
);
ExecutorService service = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 3; i++) {
int finalI = i;
service.submit(() -> {
try {
System.out.println("Thread-" + finalI + "Merhele-1 de ishleyir");
Thread.sleep(finalI * 1000);
barrier.await();
System.out.println("Thread-" + finalI + "Merhele-2 de ishleyir");
barrier.await();
} catch (InterruptedException |
BrokenBarrierException e) {
e.printStackTrace();
}
});
}
service.shutdown();
}
}
package az.etibarli;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Oca {
public static void main(String[] args) throws Exception {
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("=== Merhele tamamlandi! ===")
);
ExecutorService service = Executors.newFixedThreadPool(3);
service.submit(() -> {
try {
// Mərhələ 1
System.out.println("Fayl: oxuyuram...");
Thread.sleep(1000);
barrier.await();
// Mərhələ 2
System.out.println("Fayl: emal edirəm...");
Thread.sleep(2000);
barrier.await();
// Mərhələ 3
System.out.println("Fayl: yazıram...");
Thread.sleep(3000);
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
service.submit(() -> {
try {
System.out.println("DB: oxuyuram...");
Thread.sleep(2000);
barrier.await();
System.out.println("DB: emal edirəm...");
Thread.sleep(3000);
barrier.await();
System.out.println("DB: yazıram...");
Thread.sleep(4000);
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
service.submit(() -> {
try {
System.out.println("Şəbəkə: oxuyuram...");
Thread.sleep(3000);
barrier.await();
System.out.println("Şəbəkə: emal edirəm...");
Thread.sleep(4000);
barrier.await();
System.out.println("Şəbəkə: yazıram...");
Thread.sleep(5000);
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
service.shutdown();
}
}
Комментарии
Отправить комментарий