1. Java线程池的工作原理?
线程池是一种基于池化技术的思想来管理线程的工具,在线程池中维护了多个线程,通过对线程的复用,减少频繁创建和销毁线程的开销。
线程池的原理主要包括以下几个关键点:
- 线程池的创建:在创建线程池时,可以指定线程池的核心线程数、最大线程数、线程存活时间等参数。线程池会根据这些参数来动态调整线程数量,以满足任务的需求。
- 任务提交和执行:当有任务需要执行时,可以通过将任务提交给线程池来执行。线程池会根据任务的类型和当前线程池的状态来决定如何执行任务,包括是否使用空闲线程、创建新线程或者将任务放入等待队列中等。
- 线程复用:线程池中的线程可以被重复使用来执行多个任务,从而避免了频繁地创建和销毁线程的开销。这种线程的复用可以提高应用程序的性能和响应速度。
- 任务队列:线程池通常会使用任务队列来存储等待执行的任务。当线程池中的线程都在执行任务时,新提交的任务会被放入任务队列中等待执行。
- 线程池的状态管理:线程池会维护自身的状态,包括活动线程数、任务队列中的任务数等。通过管理线程池的状态,可以更好地控制线程的数量和任务的执行顺序。
线程池的分类:FixedThreadPool/CachedThreadPool/ScheduledThreadPool/SingleThreadExecutor 线程池的基本用法
// 创建线程的工厂
ThreadFactory factory = new ThreadFactory() {
final AtomicInteger count = new AtomicInteger();
@Override
public Thread newThread(@NotNull Runnable r) {
return new Thread(r, "Thread #" + count.getAndIncrement());
}
};
ThreadPoolExecutor executor = new ThreadPoolExecutor(
// 核心线程数,默认情况下会一直存活,如果设置了allowCoreThreadTimeOut设置为true,由keepAliveTime控制
3,
// 线程池最大线程数,达到这个数值后,新任务会被阻塞
10,
// 默认指非核心线程的闲置超时时长
60,
TimeUnit.SECONDS,
// 线程池的任务队列,通过线程池的execute方法提交的Runnable对象超过核心线程数后会存储在这个参数中
new LinkedBlockingQueue<Runnable>(128),
// 线程工厂
factory
// 还有rejectedExecutionHandler
);
// 运行一个新的线程
executor.execute(()->{
});
// 线程池关闭
executor.shutdown();
executor.shutdownNow();
// 测试1
for (int i = 0; i < 3; i++) {
executor.execute(()->{
try {
while(true){
Thread.sleep(1000);
System.out.println("sleep 1000" + Thread.currentThread().getName());
// 此时队列中个数为0
System.out.println(executor.getQueue().size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 测试2
for (int i = 0; i < 4; i++) {
executor.execute(()->{
try {
while(true){
Thread.sleep(1000);
System.out.println("sleep 1000" + Thread.currentThread().getName());
// 此时队列中个数为1
System.out.println(executor.getQueue().size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 测试3
for (int i = 0; i < 14; i++) {
executor.execute(()->{
try {
while(true){
Thread.sleep(1000);
System.out.println("sleep 1000" + Thread.currentThread().getName());
// 此时队列中个数为11
System.out.println(executor.getQueue().size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
2. Java线程都有哪些状态?
线程6个状态:New / Runnable/ Blocked/ Waiting/ Timed_Waiting/ Terminated
public enum State {
// 未启动的状态
NEW,
// 正在运行的状态
RUNNABLE,
// 正在等待一个monitor lock去进入一个synchronized块/方法或者重进入synchronize块在调用Object.wait方法后
BLOCKED,
// 调用后Object.wait (with no timeout)/ Thread.join (with no timeout)/ LockSupport.park后处于这个状态
// 比如一个线程调用某个对象的Object.wait(),该对象正在等待其他线程调用该对象的Object.notify()/notifyAll()方法。
// 或者一个线程调用Thread.join后正在等待指定线程的终结
WAITING,
// 线程等待一个特定的时间,Thread.sleep / Object.wait(with timeout)/ Thread.join( with timeout)
// LockSupport.parkNanos / LockSupport.parkUntil
TIMED_WAITING,
// 线程终结
TERMINATED;
}
3. 在Java中,常见的并发库和工具
- java.util.concurrent包:Java标准库中的java.util.concurrent包提供了一系列用于并发编程的工具和类。其中包括Executor框架、ConcurrentHashMap、BlockingQueue、CountDownLatch、Semaphore等用于线程管理和同步的类。
- java.util.concurrent.locks包:该包提供了Lock接口及其实现类ReentrantLock、ReadWriteLock接口及其实现类ReentrantReadWriteLock等,用于更灵活地进行锁定和解锁操作。
- java.util.concurrent.atomic包:该包提供了一系列原子操作类,如AtomicInteger、AtomicLong、AtomicReference等,用于在多线程环境下进行原子操作,避免出现竞态条件。