There are two main ways to create threads in Java:
Thread
class:class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
Runnable
interface:class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable is running");
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
A thread in Java can be in one of the following states:
synchronized
keyword:class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + counter.getCount());
}
}
The producer - consumer pattern is a classic concurrency pattern where one or more producer threads produce data and put it into a shared buffer, and one or more consumer threads consume the data from the buffer.
import java.util.LinkedList;
import java.util.Queue;
class ProducerConsumerExample {
private static final Queue<Integer> buffer = new LinkedList<>();
private static final int MAX_SIZE = 5;
static class Producer implements Runnable {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
synchronized (buffer) {
while (buffer.size() == MAX_SIZE) {
buffer.wait();
}
buffer.add(i);
System.out.println("Produced: " + i);
buffer.notifyAll();
}
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
synchronized (buffer) {
while (buffer.isEmpty()) {
buffer.wait();
}
int item = buffer.poll();
System.out.println("Consumed: " + item);
buffer.notifyAll();
}
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread producerThread = new Thread(new Producer());
Thread consumerThread = new Thread(new Consumer());
producerThread.start();
consumerThread.start();
}
}
Thread pooling is a technique where a fixed number of threads are created in advance and are reused to execute multiple tasks. Java provides the ExecutorService
interface and its implementations for thread pooling.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
Java provides many high - level concurrency utilities in the java.util.concurrent
package, such as ConcurrentHashMap
, CountDownLatch
, CyclicBarrier
, etc. These utilities are more robust and easier to use than low - level synchronization mechanisms.
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key1", 1);
map.put("key2", 2);
System.out.println(map.get("key1"));
}
}
Concurrency in Java multi - threading is a powerful but complex topic. By understanding the fundamental concepts, usage methods, common practices, and best practices, you can write more efficient and reliable concurrent programs. Remember to always be aware of race conditions, deadlocks, and other concurrency issues, and use the appropriate synchronization mechanisms and high - level concurrency utilities provided by Java.