元婴期

15. Java 中的同步(synchronization)机制是什么?如何使用 synchronized 关键字?

同步机制Java 中用于解决并发问题的关键手段。多线程访问共享资源时,可能会导致数据不一致。

synchronized 关键字用于确保同一时间只有一个线程可以访问共享资源。

实例方法同步:整个方法被锁定,同一时间只能有一个线程执行该方法。

代码块同步:锁定某个对象,用于更细粒度的同步控制。

class Counter {
    private int count = 0;

    // 同步方法
    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

public class SynchronizationExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        // 创建多个线程同时访问共享资源
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                counter.increment();
            }
        });

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

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("Final count: " + counter.getCount());
    }
}

synchronized 确保同一时间只有一个线程可以访问 increment() 方法,避免竞争条件。


16. 什么是 wait()notify()notifyAll()?它们在线程通信中的作用是什么?

wait()notify()notifyAll()Java 中的线程通信机制,常用于同步块内的线程协调:

wait():使当前线程进入等待状态,释放锁,直到其他线程调用 notify()notifyAll()

notify():唤醒一个正在等待的线程。

notifyAll():唤醒所有等待的线程。

class Message {
    private String msg;

    public Message(String str) {
        this.msg = str;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String str) {
        this.msg = str;
    }
}

class Waiter implements Runnable {
    private Message msg;

    public Waiter(Message m) {
        this.msg = m;
    }

    public void run() {
        synchronized (msg) {
            try {
                System.out.println("Waiting for message...");
                msg.wait(); // 线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Received message: " + msg.getMsg());
        }
    }
}

class Notifier implements Runnable {
    private Message msg;

    public Notifier(Message m) {
        this.msg = m;
    }

    public void run() {
        synchronized (msg) {
            msg.setMsg("Notification complete");
            msg.notify(); // 唤醒等待的线程
        }
    }
}

public class WaitNotifyExample {
    public static void main(String[] args) throws InterruptedException {
        Message msg = new Message("Process it");

        Thread waiter = new Thread(new Waiter(msg));
        Thread notifier = new Thread(new Notifier(msg));

        waiter.start();
        Thread.sleep(1000);
        notifier.start();
    }
}

wait() 让线程进入等待状态,notify() 唤醒等待的线程,notifyAll() 则唤醒所有等待的线程。


17. 什么是线程池(Thread Pool)?如何使用 ExecutorService 管理线程?

线程池 是一种优化多线程管理的方式,减少频繁创建和销毁线程的开销。

ExecutorService 提供了创建和管理线程池的机制。

Fixed Thread Pool:指定固定大小的线程池。

Cached Thread Pool:根据需要动态创建线程。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {
    public static void main(String[] args) {
        // 创建固定大小的线程池
        ExecutorService executor = Executors.newFixedThreadPool(3);

        for (int i = 1; i <= 5; i++) {
            final int taskID = i;
            executor.submit(() -> {
                System.out.println("Task " + taskID + " is running");
            });
        }

        executor.shutdown(); // 关闭线程池
    }
}

ExecutorService 管理一组线程,避免频繁创建销毁。shutdown() 用于在任务完成后关闭线程池。


18. 什么是 Lambda 表达式?Java 中如何使用 Lambda 表达式?

Lambda 表达式Java 8 引入的一个简洁的匿名函数表达式,用于实现函数式接口。Lambda 表达式使得代码更简洁,特别是对于匿名内部类的使用。

  • 语法(parameters) -> expression(parameters) -> {statements}
import java.util.Arrays;
import java.util.List;

public class LambdaExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用 Lambda 表达式遍历列表
        names.forEach(name -> System.out.println(name));

        // 使用 Lambda 实现 Runnable
        new Thread(() -> System.out.println("Lambda thread running")).start();
    }
}

Lambda 表达式使代码更加简洁和可读,特别适用于简单的操作,例如遍历集合或实现 Runnable 接口。


19. Java 中的 final 关键字有什么作用?可以用在哪些地方?

final 关键字用于限制修改,主要有以下几种用法:

变量:声明为 final 的变量只能赋值一次,之后不能修改。

方法:声明为 final 的方法不能在子类中重写。

:声明为 final 的类不能被继承。

// final 变量
public class FinalExample {
    public static void main(String[] args) {
        final int MAX_VALUE = 100;
        // MAX_VALUE = 200; // 错误:不能修改 final 变量
        System.out.println(MAX_VALUE);
    }
}

// final 类
final class Car {
    public void run() {
        System.out.println("Car is running");
    }
}

// final 方法
class Vehicle {
    public final void start() {
        System.out.println("Vehicle started");
    }
}

20. 什么是 Java 的自动装箱(Autoboxing)和拆箱(Unboxing)?它们如何工作?

自动装箱Java 自动将基本数据类型转换为其对应的包装类,例如 int 转换为 Integer

拆箱 则是 Java 自动将包装类转换为基本数据类型,例如 Integer 转换为 int

public class BoxingExample {
    public static void main(String[] args) {
        // 自动装箱
        Integer intObj = 100; // 自动将 int 转换为 Integer

        // 拆箱
        int intValue = intObj; // 自动将 Integer 转换为 int

        System.out.println("Integer: " + intObj);
        System.out.println("int: " + intValue);
    }
}

装箱和拆箱使得基本类型与包装类型之间的转换更加简单和自动化。


21. 什么是 Java 的内存模型(Memory Model)?如何管理对象的生命周期和垃圾回收?

Java 内存模型(Java Memory Model, JMM)定义了线程如何通过共享变量进行交互和如何保证可见性。

它规定了:

堆内存:存储对象和实例变量,由所有线程共享。

栈内存:存储局部变量和方法调用,每个线程拥有自己的栈。

Java垃圾回收(Garbage Collection, GC) 自动管理对象的生命周期,释放不再使用的对象所占用的内存,避免内存泄漏。垃圾回收通常使用标记-清除算法来实现。

public class GarbageCollectionExample {
    public static void main(String[] args) {
        GarbageCollectionExample obj = new GarbageCollectionExample();
        obj = null; // 使对象不可达

        // 手动请求垃圾回收
        System.gc();
        System.out.println("Garbage collection requested");
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("Garbage collected");
    }
}

System.gc() 请求垃圾回收,finalize() 方法在对象被回收时调用(不建议依赖 finalize() 进行资源管理)。

results matching ""

    No results matching ""