Java多线程编程是现代软件开发中的一项关键技术,它允许程序在同一时刻执行多个任务,从而提高程序的性能和响应能力。接下来,我们将通过几个具体的示例来探讨Java多线程编程的奥秘,并介绍如何在实践中使用多线程。
创建线程
在Java中,创建线程有两种常见的方式:继承Thread
类和实现Runnable
接口。
继承Thread类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
实现Runnable接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
线程同步
线程同步是为了保证多个线程之间的数据一致性。Java提供了多种同步机制,包括synchronized
关键字和ReentrantLock
等。
使用synchronized关键字
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final count: " + counter.getCount());
}
}
使用ReentrantLock
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final count: " + counter.getCount());
}
}
线程间通信
线程间通信是指线程之间通过共享数据或信号来协同工作的机制。Java提供了wait()
、notify()
和notifyAll()
等方法来实现线程间通信。
使用wait()和notify()
class ProducerConsumer {
private int count = 0;
private final Object lock = new Object();
public void produce() {
synchronized (lock) {
if (count == 0) {
count = 1;
System.out.println("Produced: " + count);
lock.notify();
} else {
try {
System.out.println("Waiting...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void consume() {
synchronized (lock) {
if (count != 0) {
count = 0;
System.out.println("Consumed: " + count);
lock.notify();
} else {
try {
System.out.println("Waiting...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Main {
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
Thread producer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
pc.produce();
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 5; i++) {
pc.consume();
}
});
producer.start();
consumer.start();
}
}
死锁预防
死锁是指两个或多个线程互相等待对方持有的资源而不释放自己的资源,导致所有线程都无法继续执行的情况。为了避免死锁,可以采取以下措施:
- 避免嵌套锁定:确保不会在一个锁持有期间请求另一个锁。
- 使用锁顺序:始终按照相同的顺序获取锁。
- 使用超时:尝试获取锁时设置超时,以避免无限期等待。
结论
Java多线程编程是一项复杂但极其重要的技术,它能够显著提高程序的并发性能。通过上述示例,我们可以看到如何创建线程、同步线程、实现线程间通信以及预防死锁。掌握这些基础知识和技术,将有助于开发者在实际项目中更好地利用多线程的优势。