java多线程6

 

1.  synchronized 关键字

 

- 基本用法和特点:用于实现线程同步,保证同一时刻仅有一个线程能访问被同步的代码块或方法。既可以修饰方法,也能修饰代码块 ,如 synchronized (锁对象) { }  ,其中锁对象可以是任意对象。

- 可重入性:同一线程持有锁时,可再次进入被该锁同步的区域。比如递归方法被 synchronized 修饰,递归调用时线程无需重新获取锁。

- 死锁问题

- 死锁场景:一个线程连续两次获取同一把锁;两个线程交叉获取锁(线程1持有锁A,等待锁B,线程2持有锁B,等待锁A );多个线程竞争有限数量的锁(如哲学家就餐问题 ) 。

- 死锁必要条件:互斥、不可抢占、请求和保持、循环等待 。

- 代码示例

 

public class SynchronizedExample {

    private static final Object lock = new Object();

    public static void main(String[] args) {

        Thread thread1 = new Thread(() -> {

            synchronized (lock) {

                System.out.println("Thread 1 acquired the lock");

                try {

                    Thread.sleep(2000);

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        });

 

        Thread thread2 = new Thread(() -> {

            synchronized (lock) {

                System.out.println("Thread 2 acquired the lock");

            }

        });

 

        thread1.start();

        try {

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        thread2.start();

    }

}

 

 

2.  volatile 关键字

 

- 作用:解决内存可见性问题,禁止编译器对该变量相关操作进行优化,确保不同线程对该变量的读取为最新值。

- 代码示例

 

public class VolatileExample {

    private static volatile boolean flag = false;

    public static void main(String[] args) {

        new Thread(() -> {

            while (!flag) {

                // 等待flag变为true

            }

            System.out.println("Flag is true, thread is running");

        }).start();

 

        try {

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

 

        flag = true;

    }

}

 

 

3.  wait 和 notify 方法

 

- 所属及功能:是 Object 类的方法,用于协调线程执行顺序。 wait 使当前线程进入等待状态并释放锁; notify 唤醒在同一个对象上等待的某个线程, notifyAll 唤醒所有等待线程 。

- 使用要求: wait 需在 synchronized 代码块内使用,否则会抛出 IllegalMonitorStateException 异常。

- 代码示例

 

public class WaitNotifyExample {

    private static final Object lock = new Object();

    public static void main(String[] args) {

        Thread thread1 = new Thread(() -> {

            synchronized (lock) {

                try {

                    System.out.println("Thread 1 is waiting");

                    lock.wait();

                    System.out.println("Thread 1 is notified");

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        });

 

        Thread thread2 = new Thread(() -> {

            synchronized (lock) {

                System.out.println("Thread 2 is notifying");

                lock.notify();

            }

        });

 

        thread1.start();

        try {

            Thread.sleep(1000);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        thread2.start();

    }

}

 

 

4. 单例模式 - 懒汉式

 

- 普通懒汉式(线程不安全):在第一次调用 getInstance 方法时创建实例,在多线程环境下可能创建多个实例。

- 线程安全的懒汉式(双重检查锁定):通过双重检查( if (instance == null)  )和 synchronized 关键字保证线程安全,延迟实例创建。使用 volatile 修饰实例变量防止指令重排,避免对象未完成初始化就被其他线程获取使用。

- 代码示例

- 普通懒汉式单例(线程不安全)

 

public class SingletonLazyUnsafe {

    private static SingletonLazyUnsafe instance;

    private SingletonLazyUnsafe() {}

    public static SingletonLazyUnsafe getInstance() {

        if (instance == null) {

            instance = new SingletonLazyUnsafe();

        }

        return instance;

    }

}

 

 

- 线程安全的懒汉式单例(双重检查锁定)

 

public class SingletonLazySafe {

    private static volatile SingletonLazySafe instance;

    private static final Object locker = new Object();

    private SingletonLazySafe() {}

    public static SingletonLazySafe getInstance() {

        if (instance == null) {

            synchronized (locker) {

                if (instance == null) {

                    instance = new SingletonLazySafe();

                }

            }

        }

        return instance;

    }

}

 

 

5. 指令重排序

 

- 概念:属于编译器优化手段,在确保逻辑一致的前提下调整代码顺序以提高效率,但在多线程环境下可能引发线程安全问题。例如创建对象操作(申请内存空间、初始化、将内存地址保存到引用变量 )可能因指令重排导致顺序改变,进而引发问题。

 

6.  BlockingQueue 

 
- 概念:Java并发包中的接口,支持阻塞的插入和移除操作。当队列满时,插入操作会阻塞等待空间可用;当队列空时,移除操作会阻塞等待元素可用 。
 
- 优点:减少资源竞争、提升效率;降低耦合;错峰平谷 。
 
- 缺点:使系统更复杂;可能增加网络开销 。
 
- 自定义实现思路:需考虑线程安全(两个线程操作同一个队列的 put/take  )和引入阻塞机制。实现时使用 synchronized 同步代码块保证操作原子性,通过 wait 和 notify 实现阻塞和唤醒 。
 
- 代码示例(简单模拟 BlockingQueue 实现)
 
java
import java.util.Arrays;
 
public class CustomBlockingQueue<T> {
    private T[] queue;
    private int head;
    private int tail;
    private int size;
    private static final int DEFAULT_CAPACITY = 10;
    private final Object lock = new Object();
 
    public CustomBlockingQueue() {
        this(DEFAULT_CAPACITY);
    }
 
    public CustomBlockingQueue(int capacity) {
        queue = (T[]) new Object[capacity];
        head = 0;
        tail = 0;
        size = 0;
    }
 
    public void put(T item) throws InterruptedException {
        synchronized (lock) {
            while (size == queue.length) {
                lock.wait();
            }
            queue[tail] = item;
            tail = (tail + 1) % queue.length;
            size++;
            lock.notify();
        }
    }
 
    public T take() throws InterruptedException {
        synchronized (lock) {
            while (size == 0) {
                lock.wait();
            }
            T item = queue[head];
            head = (head + 1) % queue.length;
            size--;
            lock.notify();
            return item;
        }
    }
}
 
 

7. 线程池( ThreadPoolExecutor )

 
- 概念:多线程处理形式,维护线程队列,复用线程执行任务,提高线程利用率和程序性能 。
 
- 优点:降低资源消耗(减少线程创建销毁开销 );提高响应速度(无需等待线程创建 );便于管理(控制并发量和资源使用 ) 。
 
- 缺点:线程池大小难精确设置(过大过小都有问题 );任务队列可能溢出(任务提交过快时 ) 。
 
- 构造参数: corePoolSize (核心线程数)、 maximumPoolSize (最大线程数)、 keepAliveTime (线程空闲时间)、 unit (时间单位)、 workQueue (任务队列)、 threadFactory (线程工厂)、 handler (拒绝策略) 。
 
- 使用场景:适用于大量、重复性任务场景,如Web服务器处理请求、批量数据处理等 。
 
- 代码示例
 
java
import java.util.concurrent.*;
 
public class ThreadPoolExecutorExample {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2, 
                4, 
                60, 
                TimeUnit.SECONDS, 
                new LinkedBlockingQueue<>(5), 
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
 
        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                try {
                    Thread.sleep(1000);
                    System.out.println("Task executed in thread: " + Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
 
        executor.shutdown();
    }
}
 
 

8. 生产者 - 消费者模型

 
- 概念:借助容器(如阻塞队列)解决生产者和消费者的强耦合问题,生产者生产数据放入容器,消费者从容器取出数据处理 。
 
- 优点:解耦(生产者和消费者不直接交互 );支持并发(两者可同时执行 );错峰平谷(缓冲生产消费速度差异 ) 。
 
- 缺点:增加系统复杂度(引入容器和同步控制逻辑 );可能出现资源竞争(容器操作同步不当 ) 。
 
- 示例说明:以吃饺子场景为例,生产者包(生产)饺子,消费者吃(消费)饺子,饺子盆(容器)起到缓冲作用 。
 
- 代码示例(基于 BlockingQueue 实现生产者 - 消费者模型)
 
java
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
 
class Producer implements Runnable {
    private BlockingQueue<String> queue;
    public Producer(BlockingQueue<String> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        try {
            queue.put("product1");
            queue.put("product2");
            queue.put("product3");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 
class Consumer implements Runnable {
    private BlockingQueue<String> queue;
    public Consumer(BlockingQueue<String> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        try {
            System.out.println(queue.take());
            System.out.println(queue.take());
            System.out.println(queue.take());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 
public class ProducerConsumerExample {
    public static void main(String[] args) {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>(3);
        Thread producerThread = new Thread(new Producer(queue));
        Thread consumerThread = new Thread(new Consumer(queue));
 
        producerThread.start();
        consumerThread.start();
 
        try {
            producerThread.join();
            consumerThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
 
 

9. 综合复习与面试相关

 
- 综合复习:对 synchronized 、 volatile 、单例模式、 BlockingQueue 、线程池、生产者 - 消费者模型等多线程相关知识点进行综合复习,强调各知识点在实际开发中的应用场景、注意事项以及它们之间的关联。
 
- 面试相关:面试中可能涉及这些多线程知识点,建议扎实掌握原理和代码实现,通过刷题、项目实践加深理解,同时注意代码规范和注释,以便在面试中清晰准确作答。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值