在Java中,线程同步和通信是非常重要的概念,用于确保多个线程之间的数据同步和协调操作。下面是一个详细的Java多线程编程教程,涵盖线程同步和通信的基本概念和实践方法。

1. 线程同步

线程同步是指多个线程在访问共享资源时保证数据的一致性和正确性。在Java中,可以使用synchronized关键字来实现线程同步。

1.1 使用synchronized关键字

public class SynchronizedExample {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }

    public static void main(String[] args) {
        SynchronizedExample example = new SynchronizedExample();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Count: " + example.getCount());
    }
}

在上面的例子中,increment()getCount()方法都使用了synchronized关键字,确保了多个线程访问count变量时的线程安全性。

1.2 使用Lock对象

除了synchronized关键字外,还可以使用Java.util.concurrent包中的Lock对象来实现线程同步。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockExample {
    private int count = 0;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }

    public int getCount() {
        return count;
    }

    public static void main(String[] args) {
        LockExample example = new LockExample();

        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                example.increment();
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Count: " + example.getCount());
    }
}

2. 线程通信

线程通信是指多个线程之间相互协作完成任务的过程。在Java中,可以使用wait()notify()notifyAll()方法来实现线程之间的通信。

2.1 使用wait()和notify()

public class WaitNotifyExample {
    private boolean flag = false;

    public synchronized void waitForFlag() throws InterruptedException {
        while (!flag) {
            wait();
        }
    }

    public synchronized void setFlag() {
        flag = true;
        notify();
    }

    public static void main(String[] args) {
        WaitNotifyExample example = new WaitNotifyExample();

        Thread thread1 = new Thread(() -> {
            try {
                example.waitForFlag();
                System.out.println("Flag is true");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread thread2 = new Thread(() -> {
            example.setFlag();
            System.out.println("Flag is set");
        });

        thread1.start();
        thread2.start();
    }
}

在上面的例子中,waitForFlag()方法会等待flag变为true,而setFlag()方法会设置flagtrue并通知等待的线程。

2.2 使用Condition对象

除了wait()notify()方法外,还可以使用Java.util.concurrent包中的Condition对象来实现线程通信。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionExample {