Java中的多线程编程详解
Java中的多线程编程是实现并发处理的重要手段,通过多线程,程序可以同时执行多个任务,提高应用程序的效率和响应速度。本文将详细探讨Java多线程编程的各个方面,包括基本概念、线程创建、线程同步、线程间通信、线程池、并发工具类以及常见的多线程问题和解决方案。希望通过这篇文章,能够帮助读者全面掌握Java多线程编程的理论与实践。
一、多线程编程的基本概念
1.1 线程与进程
- 进程:进程是操作系统中运行的一个程序实例,每个进程都有独立的内存空间和资源。
- 线程:线程是进程中的一个执行单元,一个进程可以包含多个线程,线程共享进程的资源。
1.2 并发与并行
- 并发:并发是指多个任务在同一时间段内交替进行,可能由单个CPU通过时间片轮转实现。
- 并行:并行是指多个任务在同一时间点上同时进行,通常由多核CPU或多处理器实现。
1.3 Java中的多线程
Java提供了丰富的多线程支持,包括java.lang.Thread
类、java.util.concurrent
包中的并发工具类、线程池等,使得多线程编程变得简单而高效。
二、创建线程
2.1 继承Thread类
通过继承Thread
类,可以创建一个新的线程类,重写run
方法,定义线程的执行逻辑。
示例代码:继承Thread类创建线程
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
2.2 实现Runnable接口
通过实现Runnable
接口,可以将线程的执行逻辑写在run
方法中,然后将Runnable
对象传递给Thread
对象。
示例代码:实现Runnable接口创建线程
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable is running...");
}
}
public class RunnableExample {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
2.3 实现Callable接口
Callable
接口与Runnable
接口类似,但Callable
接口可以返回结果或抛出异常。可以通过ExecutorService
提交Callable
任务,并通过Future
获取结果。
示例代码:实现Callable接口创建线程
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Callable is running...";
}
}
public class CallableExample {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(new MyCallable());
System.out.println(future.get());
executorService.shutdown();
}
}
三、线程同步
3.1 同步方法
使用synchronized
关键字可以同步方法,确保同一时间只有一个线程可以执行该方法,避免线程间的资源竞争。
示例代码:同步方法
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
public class SynchronizedMethodExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Count: " + counter.getCount());
}
}
3.2 同步块
除了同步方法,还可以使用synchronized
关键字同步代码块,只同步某一段代码。
示例代码:同步块
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public int getCount() {
return count;
}
}
public class SynchronizedBlockExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Count: " + counter.getCount());
}
}
3.3 Volatile关键字
volatile
关键字用于标记变量在多个线程间的可见性,确保变量的修改能够及时被其他线程看到。
示例代码:使用volatile关键字
class VolatileExample {
private volatile boolean running = true;
public void start() {
new Thread(() -> {
while (running) {
System.out.println("Thread is running...");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public void stop() {
running = false;
}
public static void main(String[] args) throws InterruptedException {
VolatileExample example = new VolatileExample();
example.start();
Thread.sleep(500);
example.stop();
}
}
四、线程间通信
4.1 wait/notify机制
wait()
和notify()
方法用于线程间通信,wait()
方法使当前线程等待,notify()
方法唤醒等待的线程。
示例代码:使用wait/notify实现线程间通信
class SharedResource {
private int value = 0;
private boolean available = false;
public synchronized void produce(int newValue) throws InterruptedException {
while (available) {
wait();
}
value = newValue;
available = true;
notify();
}
public synchronized int consume() throws InterruptedException {
while (!available) {
wait();
}
available = false;
notify();
return value;
}
}
public class WaitNotifyExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
resource.produce(i);
System.out.println("Produced: " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
int value = resource.consume();
System.out.println("Consumed: " + value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
4.2 Lock和Condition
Java提供了更高级的同步工具Lock
和Condition
,可以替代synchronized
和wait/notify
,提供更灵活的线程间通信方式。
示例代码:使用Lock和Condition实现线程间通信
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class SharedResource {
private int value = 0;
private boolean available = false;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void produce(int newValue) throws InterruptedException {
lock.lock();
try {
while (available) {
condition.await();
}
value = newValue;
available = true;
condition.signal();
} finally {
lock.unlock();
}
}
public int consume() throws InterruptedException {
lock.lock();
try {
while (!available) {
condition.await();
}
available = false;
condition.signal();
return value;
} finally {
lock.unlock();
}
}
}
public class LockConditionExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
resource.produce(i);
System.out.println("Produced: " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
int value
= resource.consume();
System.out.println("Consumed: " + value);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
五、线程池
5.1 线程池的概念
线程池是一种管理和重用线程的机制,通过预创建一定数量的线程,减少了线程的创建和销毁开销,提高了系统的性能和稳定性。
5.2 Java中的线程池实现
Java通过Executor
框架提供了线程池的实现,包括ThreadPoolExecutor
、ScheduledThreadPoolExecutor
等。
示例代码:使用ExecutorService创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.submit(() -> {
System.out.println(Thread.currentThread().getName() + " is executing task.");
});
}
executorService.shutdown();
}
}
5.3 自定义线程池
可以通过ThreadPoolExecutor
类自定义线程池,以满足特定需求。
示例代码:自定义线程池
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class CustomThreadPoolExample {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, // corePoolSize
4, // maximumPoolSize
60, // keepAliveTime
TimeUnit.SECONDS, // unit
new LinkedBlockingQueue<>(10) // workQueue
);
for (int i = 0; i < 15; i++) {
executor.submit(() -> {
System.out.println(Thread.currentThread().getName() + " is executing task.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
}
}
六、并发工具类
6.1 CountDownLatch
CountDownLatch
是一个同步辅助工具,允许一个或多个线程等待其他线程完成操作。
示例代码:使用CountDownLatch
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int count = 3;
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " is running.");
latch.countDown();
}).start();
}
latch.await();
System.out.println("All threads have finished.");
}
}
6.2 CyclicBarrier
CyclicBarrier
是另一个同步辅助工具,允许一组线程相互等待,直到所有线程都到达一个公共屏障点。
示例代码:使用CyclicBarrier
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
int count = 3;
CyclicBarrier barrier = new CyclicBarrier(count, () -> {
System.out.println("All threads have reached the barrier.");
});
for (int i = 0; i < count; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " is running.");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
6.3 Semaphore
Semaphore
是一种计数信号量,用于控制同时访问特定资源的线程数量。
示例代码:使用Semaphore
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
int permits = 2;
Semaphore semaphore = new Semaphore(permits);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is running.");
Thread.sleep(2000);
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
6.4 Exchanger
Exchanger
用于在两个线程之间交换数据。
示例代码:使用Exchanger
import java.util.concurrent.Exchanger;
public class ExchangerExample {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
try {
String data = "Thread-1 data";
System.out.println("Thread-1 is exchanging data: " + data);
String receivedData = exchanger.exchange(data);
System.out.println("Thread-1 received data: " + receivedData);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
String data = "Thread-2 data";
System.out.println("Thread-2 is exchanging data: " + data);
String receivedData = exchanger.exchange(data);
System.out.println("Thread-2 received data: " + receivedData);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
七、常见的多线程问题及解决方案
7.1 死锁
死锁是指两个或多个线程相互等待,导致线程永远无法继续执行的问题。
示例代码:死锁示例
class Resource {
private final String name;
public Resource(String name) {
this.name = name;
}
public String getName() {
return name;
}
public synchronized void lock(Resource other) {
System.out.println(Thread.currentThread().getName() + " locked " + this.getName());
other.use();
}
public synchronized void use() {
System.out.println(Thread.currentThread().getName() + " using " + this.getName());
}
}
public class DeadlockExample {
public static void main(String[] args) {
Resource resourceA = new Resource("Resource A");
Resource resourceB = new Resource("Resource B");
Thread thread1 = new Thread(() -> resourceA.lock(resourceB), "Thread 1");
Thread thread2 = new Thread(() -> resourceB.lock(resourceA), "Thread 2");
thread1.start();
thread2.start();
}
}
解决方案
- 避免嵌套锁:尽量避免一个线程同时持有多个锁。
- 锁顺序:确保所有线程以相同的顺序获取锁。
- 死锁检测:使用超时机制或死锁检测工具检测和处理死锁。
7.2 竞态条件
竞态条件是指多个线程同时访问共享资源,导致程序行为不可预测的问题。
示例代码:竞态条件示例
class Counter {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class RaceConditionExample {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Count: " + counter.getCount());
}
}
解决方案
- 同步:使用
synchronized
关键字或显式锁(如ReentrantLock
)同步访问共享资源。 - 无锁算法:使用无锁算法(如
AtomicInteger
)确保线程安全。
7.3 活锁
活锁是指线程不断改变状态,无法继续执行的情况,通常是因为线程之间相互影响,导致系统无法前进。
示例代码:活锁示例
class Philosopher {
private boolean eating;
public synchronized void eat() {
if (!eating) {
eating = true;
System.out.println(Thread.currentThread().getName() + " is eating.");
}
}
public synchronized void think() {
eating = false;
System.out.println(Thread.currentThread().getName() + " is thinking.");
}
}
public class LivelockExample {
public static void main(String[] args) {
Philosopher philosopher1 = new Philosopher();
Philosopher philosopher2 = new Philosopher();
Thread thread1 = new Thread(() -> {
while (true) {
philosopher1.eat();
philosopher1.think();
}
}, "Philosopher 1");
Thread thread2 = new Thread(() -> {
while (true) {
philosopher2.eat();
philosopher2.think();
}
}, "Philos
opher 2");
thread1.start();
thread2.start();
}
}
解决方案
- 随机化:在遇到冲突时引入随机等待时间,减少线程相互影响的可能性。
- 优先级:使用优先级机制,确保某些线程可以优先执行。
7.4 线程饥饿
线程饥饿是指某些线程长时间无法获取资源,导致无法继续执行的情况。
示例代码:线程饥饿示例
class SharedResource {
private final Object lock = new Object();
public void use() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " is using resource.");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadStarvationExample {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(resource::use, "Thread " + i);
thread.setPriority(i == 9 ? Thread.MAX_PRIORITY : Thread.MIN_PRIORITY);
thread.start();
}
}
}
解决方案
- 公平锁:使用公平锁(如
ReentrantLock
的公平模式)确保资源分配的公平性。 - 调整优先级:合理设置线程优先级,避免某些线程长时间处于等待状态。
八、多线程编程的最佳实践
8.1 避免死锁
- 最小化锁的使用:尽量减少锁的使用,避免复杂的锁嵌套。
- 锁的顺序:确保所有线程以相同的顺序获取锁。
- 使用超时:在获取锁时设置超时,避免长时间等待。
8.2 使用并发工具类
Java的java.util.concurrent
包提供了丰富的并发工具类,如ConcurrentHashMap
、CopyOnWriteArrayList
等,使用这些工具类可以简化并发编程,提高程序的性能和可靠性。
8.3 优先选择不可变对象
不可变对象是线程安全的,可以在多个线程间安全共享。尽量使用不可变对象,减少线程同步的需求。
8.4 线程池的合理使用
合理使用线程池可以提高系统的性能和稳定性,避免频繁创建和销毁线程带来的开销。
- 选择合适的线程池类型:根据任务的特点选择合适的线程池类型,如固定线程池、缓存线程池、定时线程池等。
- 设置合理的线程池参数:根据系统的负载和资源情况,设置合适的核心线程数、最大线程数和队列容量。
8.5 合理处理异常
在多线程编程中,合理处理异常非常重要。未捕获的异常可能导致线程意外终止,影响系统的稳定性。
- 捕获并处理异常:在线程的执行代码中捕获并处理异常,确保线程正常运行。
- 使用线程池时设置异常处理器:在使用线程池时,可以设置全局的异常处理器,统一处理线程异常。
九、Java中的并发工具类详解
9.1 ConcurrentHashMap
ConcurrentHashMap
是线程安全的哈希表实现,支持并发访问。相比于Hashtable
和Collections.synchronizedMap
,ConcurrentHashMap
在并发环境下性能更高。
示例代码:使用ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 插入元素
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
// 获取元素
System.out.println("Value for key 'one': " + map.get("one"));
// 遍历元素
map.forEach((key, value) -> {
System.out.println(key + ": " + value);
});
}
}
9.2 CopyOnWriteArrayList
CopyOnWriteArrayList
是线程安全的列表实现,通过在写操作时创建数组副本,确保读操作的并发性。适用于读多写少的场景。
示例代码:使用CopyOnWriteArrayList
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
List<String> list = new CopyOnWriteArrayList<>();
// 插入元素
list.add("one");
list.add("two");
list.add("three");
// 获取元素
System.out.println("Element at index 1: " + list.get(1));
// 遍历元素
list.forEach(System.out::println);
}
}
9.3 BlockingQueue
BlockingQueue
是一个支持阻塞操作的队列,常用于生产者-消费者模式。ArrayBlockingQueue
和LinkedBlockingQueue
是两种常见的实现。
示例代码:使用BlockingQueue
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class Producer implements Runnable {
private BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("Produced: " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int value = queue.take();
System.out.println("Consumed: " + value);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class BlockingQueueExample {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
new Thread(producer).start();
new Thread(consumer).start();
}
}
9.4 ForkJoinPool
ForkJoinPool
是Java 7引入的一种并行执行框架,适用于大规模并行任务的分而治之。ForkJoinTask
是任务的基本单位,可以递归地分解任务并合并结果。
示例代码:使用ForkJoinPool
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class SumTask extends RecursiveTask<Integer> {
private static final int THRESHOLD = 5;
private int[] arr;
private int start;
private int end;
public SumTask(int[] arr, int start, int end) {
this.arr = arr;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
if (end - start <= THRESHOLD) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += arr[i];
}
return sum;
} else {
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(arr, start, mid);
SumTask rightTask = new SumTask(arr, mid, end);
leftTask.fork();
rightTask.fork();
return leftTask.join() + rightTask.join();
}
}
}
public class ForkJoinPoolExample {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
ForkJoinPool pool = new ForkJoinPool();
SumTask task = new SumTask(arr, 0, arr.length);
int result = pool.invoke(task);
System.out.println("Sum: " + result);
}
}
十、Java多线程编程实战案例
10.1 多线程下载器
实现一个多线程下载器,可以同时下载多个文件,提高下载速度。
示例代码:多线程下载器
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class DownloadTask implements Runnable {
private String fileURL;
private String savePath;
public DownloadTask(String fileURL, String savePath) {
this.fileURL = fileURL;
this.savePath = savePath;
}
@Override
public void run() {
try (BufferedInputStream in = new BufferedInputStream(new URL(file
URL).openStream());
FileOutputStream out = new FileOutputStream(savePath)) {
byte[] data = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
out.write(data, 0, count);
}
System.out.println("Downloaded: " + fileURL);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MultiThreadedDownloader {
public static void main(String[] args) {
String[] fileURLs = {
"http://example.com/file1",
"http://example.com/file2",
"http://example.com/file3"
};
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (String fileURL : fileURLs) {
String savePath = "C:/downloads/" + fileURL.substring(fileURL.lastIndexOf('/') + 1);
executorService.submit(new DownloadTask(fileURL, savePath));
}
executorService.shutdown();
}
}
10.2 并行数据处理
实现一个并行数据处理系统,使用多线程对大数据集进行并行处理。
示例代码:并行数据处理
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class DataProcessorTask extends RecursiveTask<int[]> {
private static final int THRESHOLD = 1000;
private int[] data;
private int start;
private int end;
public DataProcessorTask(int[] data, int start, int end) {
this.data = data;
this.start = start;
this.end = end;
}
@Override
protected int[] compute() {
if (end - start <= THRESHOLD) {
for (int i = start; i < end; i++) {
data[i] *= 2; // 简单的处理:数据乘以2
}
return data;
} else {
int mid = (start + end) / 2;
DataProcessorTask leftTask = new DataProcessorTask(data, start, mid);
DataProcessorTask rightTask = new DataProcessorTask(data, mid, end);
leftTask.fork();
rightTask.fork();
leftTask.join();
rightTask.join();
return data;
}
}
}
public class ParallelDataProcessing {
public static void main(String[] args) {
int[] data = new int[10000];
for (int i = 0; i < data.length; i++) {
data[i] = i;
}
ForkJoinPool pool = new ForkJoinPool();
DataProcessorTask task = new DataProcessorTask(data, 0, data.length);
pool.invoke(task);
for (int value : data) {
System.out.println(value);
}
}
}
10.3 多线程Web服务器
实现一个简单的多线程Web服务器,能够处理多个客户端的请求。
示例代码:多线程Web服务器
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class ClientHandler implements Runnable {
private Socket clientSocket;
public ClientHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {
String request;
while ((request = in.readLine()) != null) {
if (request.isEmpty()) {
break;
}
System.out.println("Received: " + request);
}
String response = "HTTP/1.1 200 OK\r\n\r\nHello, World!";
out.println(response);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MultiThreadedWebServer {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
try (ServerSocket serverSocket = new ServerSocket(8080)) {
System.out.println("Server is listening on port 8080");
while (true) {
Socket clientSocket = serverSocket.accept();
System.out.println("New client connected");
executorService.submit(new ClientHandler(clientSocket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
十一、Java多线程编程的未来趋势
11.1 异步编程模型
随着Java不断发展,异步编程模型逐渐成为主流。CompletableFuture
和Reactive Streams
等新特性,使得开发者可以更方便地编写高效的异步代码。
11.2 并行流
Java 8引入的并行流,使得开发者可以使用简单的流API实现并行处理,提高程序性能。
11.3 轻量级线程
Java的项目Loom正在开发轻量级线程(也称为纤程),旨在提高并发编程的效率和可扩展性。轻量级线程将大幅简化高并发编程,提高程序的性能和响应速度。
十二、总结
Java多线程编程是实现并发处理的重要手段,通过合理使用多线程,可以显著提高应用程序的效率和响应速度。本文详细介绍了Java多线程编程的基本概念、线程创建、线程同步、线程间通信、线程池、并发工具类以及常见的多线程问题和解决方案。同时,还提供了多个实战案例,帮助读者更好地理解和应用多线程编程。