← 返回首页

Java并发编程基础:线程与同步

📂 java ⏱ 5 min 846 words

Java并发编程基础:线程与同步

概述

并发编程是Java的重要特性,它允许多个线程同时执行任务。本教程介绍线程的创建、同步机制和线程安全问题。

1. 创建线程

方式1:继承Thread类

public class ThreadDemo {
    public static void main(String[] args) {
        // 创建线程
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println("线程1: " + i);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        
        thread1.start();
        
        // 方式2:实现Runnable接口
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println("线程2: " + i);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        
        Thread thread2 = new Thread(runnable);
        thread2.start();
        
        // 方式3:Lambda表达式(Java 8+)
        Thread thread3 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("线程3: " + i);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread3.start();
    }
}

方式2:实现Callable接口

import java.util.concurrent.*;

public class CallableDemo {
    public static void main(String[] args) {
        // 创建Callable任务
        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 1; i <= 100; i++) {
                    sum += i;
                }
                return sum;
            }
        };
        
        // 使用FutureTask包装
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        
        // 启动线程
        Thread thread = new Thread(futureTask);
        thread.start();
        
        try {
            // 获取结果
            Integer result = futureTask.get();
            System.out.println("计算结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 线程同步

synchronized关键字

public class SynchronizedDemo {
    private int count = 0;
    
    // 同步方法
    public synchronized void increment() {
        count++;
    }
    
    // 同步代码块
    public void decrement() {
        synchronized (this) {
            count--;
        }
    }
    
    public int getCount() {
        return count;
    }
    
    public static void main(String[] args) throws InterruptedException {
        SynchronizedDemo demo = new SynchronizedDemo();
        
        // 创建多个线程
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    demo.increment();
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("最终计数: " + demo.getCount());
    }
}

Lock接口

import java.util.concurrent.locks.*;

public class LockDemo {
    private final ReentrantLock lock = new ReentrantLock();
    private int count = 0;
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
    
    public void decrement() {
        lock.lock();
        try {
            count--;
        } finally {
            lock.unlock();
        }
    }
    
    public int getCount() {
        return count;
    }
    
    // 读写锁
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private String data = "";
    
    public String readData() {
        readLock.lock();
        try {
            return data;
        } finally {
            readLock.unlock();
        }
    }
    
    public void writeData(String newData) {
        writeLock.lock();
        try {
            data = newData;
        } finally {
            writeLock.unlock();
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        LockDemo demo = new LockDemo();
        
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    demo.increment();
                }
            });
            threads[i].start();
        }
        
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("最终计数: " + demo.getCount());
    }
}

3. 线程通信

wait/notify

public class WaitNotifyDemo {
    private final Object lock = new Object();
    private boolean hasData = false;
    
    public void produce() throws InterruptedException {
        synchronized (lock) {
            while (hasData) {
                lock.wait();
            }
            System.out.println("生产数据");
            hasData = true;
            lock.notifyAll();
        }
    }
    
    public void consume() throws InterruptedException {
        synchronized (lock) {
            while (!hasData) {
                lock.wait();
            }
            System.out.println("消费数据");
            hasData = false;
            lock.notifyAll();
        }
    }
    
    public static void main(String[] args) {
        WaitNotifyDemo demo = new WaitNotifyDemo();
        
        // 生产者线程
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    demo.produce();
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        // 消费者线程
        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    demo.consume();
                    Thread.sleep(150);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        producer.start();
        consumer.start();
    }
}

4. 实际应用示例

线程池

import java.util.concurrent.*;

public class ThreadPoolDemo {
    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("任务 " + taskId + " 执行,线程: " + 
                    Thread.currentThread().getName());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        
        // 关闭线程池
        executor.shutdown();
        try {
            executor.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("所有任务完成");
    }
}

生产者-消费者模式

import java.util.concurrent.*;

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
        
        // 生产者
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    String item = "Item-" + i;
                    queue.put(item);
                    System.out.println("生产: " + item);
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        // 消费者
        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    String item = queue.take();
                    System.out.println("消费: " + item);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        producer.start();
        consumer.start();
    }
}

5. 最佳实践

  1. 优先使用高级并发工具:ExecutorService、BlockingQueue等
  2. 避免死锁:按固定顺序获取锁
  3. 使用volatile:确保可见性
  4. 最小化同步范围:只同步必要的代码
  5. 使用线程安全集合:ConcurrentHashMap、CopyOnWriteArrayList等

总结

并发编程是Java的重要特性。掌握线程创建、同步机制和线程安全问题,可以编写高效的并发程序。在实际编程中,优先使用高级并发工具,避免低级同步错误。