1. Java中创建线程的几种方式有哪些?
答案:
- 继承
Thread
类:class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread is running.");} } new MyThread().start();
- 实现
Runnable
接口:class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Thread is running.");} } new Thread(new MyRunnable()).start();
- 实现
Callable
接口(支持返回值和异常):class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {return "Thread is running.";} } FutureTask<String> futureTask = new FutureTask<>(new MyCallable()); new Thread(futureTask).start(); System.out.println(futureTask.get());
- 使用线程池:
ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(() -> System.out.println("Thread is running.")); executor.shutdown();
2. Java中的wait()
和sleep()
的区别是什么?
答案:
-
wait()
:- 是
Object
类的方法,必须在同步方法或同步代码块中使用。 - 释放当前线程持有的锁,进入等待状态,直到被其他线程唤醒。
- 可以指定等待时间,超时后线程会自动唤醒。
- 示例:
synchronized (obj) {obj.wait(); }
- 是
-
sleep()
:- 是
Thread
类的静态方法,不会释放锁。 - 线程暂停指定时间后自动恢复运行。
- 示例:
Thread.sleep(1000);
- 是
3. 如何实现线程间的通信?
答案:
线程间通信可以通过以下方式实现:
-
使用
wait()
和notify()
/notifyAll()
:wait()
:线程释放锁并进入等待状态。notify()
/notifyAll()
:唤醒等待中的线程。- 示例:
class SharedResource {private boolean available = false;public synchronized void produce() throws InterruptedException {while (available) {wait();}System.out.println("Produced");available = true;notifyAll();}public synchronized void consume() throws InterruptedException {while (!available) {wait();}System.out.println("Consumed");available = false;notifyAll();} }
-
使用
java.util.concurrent
包中的工具类:BlockingQueue
:线程安全的队列,支持阻塞操作。- 示例:
BlockingQueue<String> queue = new LinkedBlockingQueue<>(1); queue.put("Item"); String item = queue.take();
4. Java中的线程池有哪些类型?
答案:
Java提供了多种线程池类型,每种类型适用于不同的场景:
-
Executors.newFixedThreadPool(int n)
:- 创建一个固定大小的线程池,线程数为
n
。 - 适用于任务数量较多且线程数固定的场景。
- 创建一个固定大小的线程池,线程数为
-
Executors.newSingleThreadExecutor()
:- 创建一个单线程的线程池,所有任务按顺序执行。
- 适用于任务需要按顺序执行的场景。
-
Executors.newCachedThreadPool()
:- 创建一个可缓存的线程池,线程数根据任务数量动态调整。
- 适用于任务数量不确定且线程数需要动态调整的场景。
-
Executors.newScheduledThreadPool(int corePoolSize)
:- 创建一个支持定时任务的线程池。
- 示例:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); executor.scheduleAtFixedRate(() -> System.out.println("Task executed"), 0, 1, TimeUnit.SECONDS);
5. 如何避免线程安全问题?
答案:
避免线程安全问题可以通过以下方式:
-
使用同步机制:
synchronized
方法或代码块。- 示例:
public synchronized void increment() {count++; }
-
使用
java.util.concurrent
包中的工具类:ConcurrentHashMap
:线程安全的哈希表。AtomicInteger
:线程安全的整数。- 示例:
AtomicInteger count = new AtomicInteger(0); count.incrementAndGet();
-
使用不可变对象:
- 不可变对象(如
String
、Integer
)是线程安全的,因为它们的状态不可变。
- 不可变对象(如
-
使用锁(
ReentrantLock
):- 示例:
Lock lock = new ReentrantLock(); lock.lock(); try {// Critical section } finally {lock.unlock(); }
- 示例:
6. Java中的volatile
关键字的作用是什么?
答案:
volatile
用于修饰变量,确保变量的读写操作对所有线程可见。- 它可以防止指令重排序,但不能保证复合操作的原子性。
- 示例:
private volatile boolean running = true;public void run() {while (running) {// Do something} }
7. 如何实现线程的中断?
答案:
线程可以通过以下方式中断:
-
调用
Thread.interrupt()
方法:- 设置线程的中断状态。
- 示例:
Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {// Do something} }); thread.start(); thread.interrupt();
-
在
run()
方法中检查中断状态:- 使用
Thread.currentThread().isInterrupted()
检查线程是否被中断。 - 示例:
public void run() {while (!Thread.currentThread().isInterrupted()) {// Do something} }
- 使用
8. Java中的Future
和CompletableFuture
的区别是什么?
答案:
-
Future
:- 用于异步任务的结果。
- 提供
get()
方法获取任务结果,但不支持回调。 - 示例:
Future<String> future = executor.submit(() -> "Result"); String result = future.get();
-
CompletableFuture
:- 是
Future
的增强版本,支持链式调用和回调。 - 提供
thenApply
、thenAccept
、thenCombine
等方法。 - 示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Result"); future.thenAccept(System.out::println);
- 是
9. 如何实现线程的同步?
答案:
线程同步可以通过以下方式实现:
-
使用
synchronized
关键字:- 示例:
public synchronized void increment() {count++; }
- 示例:
-
使用锁(
ReentrantLock
):- 示例:
Lock lock = new ReentrantLock(); lock.lock(); try {// Critical section } finally {lock.unlock(); }
- 示例:
-
使用
java.util.concurrent
包中的同步工具类:Semaphore
:信号量,用于控制同时访问某个资源的线程数量。- 示例:
Semaphore semaphore = new Semaphore(2); semaphore.acquire(); semaphore.release();
10. Java中的线程池如何管理线程的生命周期?
答案:
线程池通过以下方式管理线程的生命周期:
-
线程的创建:
- 线程池在初始化时创建一定数量的线程。
- 当任务提交时,线程池会根据当前线程数和任务队列的状态决定是否创建新线程。
-
线程的执行:
- 线程从任务队列中获取任务并执行。
- 如果任务队列为空,线程会等待新任务。
-
线程的销毁:
- 线程池会根据配置的
keepAliveTime
和corePoolSize
决定是否销毁空闲线程。 - 当线程池关闭时(调用
shutdown()
或shutdownNow()
- 线程池会根据配置的