一些线程基础问题
...大约 3 分钟多线程
1.并行跟并发有什么区别?
- 并行:多核 CPU 上的多任务处理,多个任务在同一时间真正地同时执行。
- 并发:单核 CPU 上的多任务处理,多个任务在同一时间段内交替执行,通过时间片轮转实现交替执行。

就好像去食堂打饭,并行就是每个人对应一个阿姨,同时打饭;而并发就是一个阿姨,轮流给每个人打饭。

2.线程的几种创建方式
- 继承 Thread 类
- 实现 Runnable 接口
- 实现 Callable 接口

第一种,继承 Thread 类,重写 run()
方法,调用 start()
方法启动线程。
class ThreadTask extends Thread {
public void run() {
System.out.println("看完二哥的 Java 进阶之路,上岸了!");
}
public static void main(String[] args) {
ThreadTask task = new ThreadTask();
task.start();
}
}
这种方法的缺点是,由于 Java 不支持多重继承,所以如果类已经继承了另一个类,就不能使用这种方法了。
第二种,实现 Runnable 接口,重写 run()
方法,然后创建 Thread 对象,将 Runnable 对象作为参数传递给 Thread 对象,调用 start()
方法启动线程。
class RunnableTask implements Runnable {
public void run() {
System.out.println("看完二哥的 Java 进阶之路,上岸了!");
}
public static void main(String[] args) {
RunnableTask task = new RunnableTask();
Thread thread = new Thread(task);
thread.start();
}
}
这种方法的优点是可以避免 Java 的单继承限制,并且更符合面向对象的编程思想,因为 Runnable 接口将任务代码和线程控制的代码解耦了。
第三种,实现 Callable 接口,重写 call()
方法,然后创建 FutureTask 对象,参数为 Callable 对象;紧接着创建 Thread 对象,参数为 FutureTask 对象,调用 start()
方法启动线程。
class CallableTask implements Callable<String> {
public String call() {
return "看完二哥的 Java 进阶之路,上岸了!";
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallableTask task = new CallableTask();
FutureTask<String> futureTask = new FutureTask<>(task);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
}
这种方法的优点是可以获取线程的执行结果。
3.Java 线程池核心线程数在运行过程中能修改吗?
可以动态修改的。Java 的 ThreadPoolExecutor
提供了动态调整核心线程数和最大线程数的方法。
1)修改核心线程数的方法:
- 使用
ThreadPoolExecutor.setCorePoolSize(int corePoolSize)
方法可以动态修改核心线程数。corePoolSize
参数代表线程池中的核心线程数,当池中线程数量少于核心线程数时,会创建新的线程来处理任务。这个修改可以在线程池运行的过程中进行,立即生效。
2)注意事项:
- 核心线程数的修改不会中断现有任务,新的核心线程数会在新任务到来时生效。
setCorePoolSize()
方法可以减少核心线程数,但如果当前线程池中的线程数量超过了新的核心线程数,多余的线程不会立即被销毁,直到这些线程空闲后被回收。
在实际生产环境中,可以通过监控线程池的状态(如当前活跃线程数、队列长度等)来决定是否动态调整线程池大小。
这在负载波动大的应用场景中非常有用,例如在负载高峰时临时增加核心线程数,低负载时通过回收空闲线程释放资源。