线程池的优势与使用方式:提升性能与资源管理的最佳实践
【原始链接】:Java线程池的四种用法和使用情况

Java线程池的四种用法和使用情况:1。以下方式存在问题
new Thread() {
@Override
public void run() {
// 业务逻辑
}}.start();
1。首先,经常创建和破坏对象是一件非常耗时的事情。
2。如果用户数量相对较大,这会导致过多的资源被占用,则由于资源不足,我们的服务可能会停机;
3。总而言之,在实际开发中,此操作实际上是一种不受欢迎的方式。
2。使用线程池的优点是什么
1。增加线程池中线的使用率,减少对象的创建和破坏;
2。线程池可以控制线程的数量,有效地改善服务器的使用资源,并避免由于资源不足而导致的停机时间;
3。使用线程池的四种方法1。NewCachedThreadPool
创建一个线程池。如果线程池中的线程数太大,则可以有效地回收不必要的线程。如果线程数不足,则可以创建新线程。
public static void method() throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
Thread.sleep(1000);
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " " + index);
}
});
}
}
执行结果
通过分析,我可以看到一个线程从头到尾执行,实现线程重复使用并且没有创建不必要的线程。
如果我们的业务需要一定时间来处理它,那会发生什么?让我们模拟它。
可以看出,现在需要几个线程进行交替执行。
不足:尽管此方法可以自动扩大根据业务方案处理我们的业务的线程数量,但我们无法控制的是,最多需要同时处理多少线程;
优点:如果第二任任务开始并且执行第一个任务时,第二个任务将重复使用第一个任务创建的线程,并且不会重新创建新线程,这将增加线程重复使用率。 ;
2。newFixedThreadPool
这样,您可以指定线程池中的线程数。例如,如果一个浴室只能容纳多达20个人可以同时洗个澡,那么从后面来的人只能在外面排队等候。如果您匆匆进去,那么只会有一种情况,摩擦和摩擦...
首先,测试最大容量是否是一个线程,这是我们预测的结果吗?
public static void method_01() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
final int index = i;
executor.execute(() -> {
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + index);
});
}
executor.shutdown();
}
执行结果
让我们将其更改为3个线程并查看结果
优点:两个结果表明,可以控制NewFixedThreadPool中的线程数,因此我们可以通过控制最大线程来控制服务器的最大使用率,并且同事可以确保不会消耗时间的流量突然增加。服务器上的资源太多。
3。newscheduledthreadpool
该线程池支持时间和定期执行。我们可以延迟任务的执行时间,也可以设置定期时间重复执行任务。有两种延迟此线程池的方法。
测试一个
public static void method_02() {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
long start = new Date().getTime();
System.out.println("scheduleAtFixedRate 开始执行时间:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = new Date().getTime();
System.out.println("scheduleAtFixedRate 执行花费时间=" + (end - start) / 1000 + "m");
System.out.println("scheduleAtFixedRate 执行完成时间:" + DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================");
}
}, 1, 5, TimeUnit.SECONDS);
}
执行结果
测试2
摘要:上述两种方法之间的差异是任务执行时间。如果间隔时间大于任务执行时间,则任务不会受到执行时间的影响。如果间隔时间小于任务执行时间,则在完成任务执行后将立即执行任务执行,并且间隔时间将被中断。
测试一个
public static void method_03() {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
long start = new Date().getTime();
System.out.println("scheduleWithFixedDelay 开始执行时间:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = new Date().getTime();
System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 +"m");
System.out.println("scheduleWithFixedDelay执行完成时间:"
+ DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================");
}
}, 1, 2, TimeUnit.SECONDS);
}
执行结果
测试2
public static void method_03() {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
long start = new Date().getTime();
System.out.println("scheduleWithFixedDelay 开始执行时间:" +
DateFormat.getTimeInstance().format(new Date()));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = new Date().getTime();
System.out.println("scheduleWithFixedDelay执行花费时间=" + (end - start) / 1000 +"m");
System.out.println("scheduleWithFixedDelay执行完成时间:"
+ DateFormat.getTimeInstance().format(new Date()));
System.out.println("======================================");
}
}, 1, 2, TimeUnit.SECONDS);
}
执行结果
摘要:类似地,就像ScheduleWithFixedDelay测试方法一样,可以测量的是,ScheduleWithFixedDelay的间隔时间不会受到任务执行时间长度的影响。
4。newsinglethreadexecutor
这是一个单个线程池,该线程从头到尾由一个线程执行。
public static void method_04() {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int index = i;
executor.execute(() -> {
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + index);
});
}
executor.shutdown();
}
执行结果
4。线程池的作用
线程池的功能主要是为了提高系统的性能和使用情况。在文章的开头,如果我们使用最简单的方法来创建线程,如果用户数量相对较大,那么将生成许多创建和销毁线程的动作,这将导致服务器在创建创建时消耗性能并破坏线程。比处理实际业务更多的时间和性能。线程池是出现的问题。
有许多具有相同想法的设计,例如数据库连接池。由于数据库连接经常连接,因此创建连接是非常耗费性能的事情,并且所有数据库连接池都出现。