彻底搞懂java多线程(三)-pg电子游戏官网

热度:3℃ 发布时间:2022-01-21 17:23:26
目录java线程池线程池的优点线程池的6种创建方式创建单个线程池的作用是什么?线程池的第七种创建方式threadpoolexecutor的执行方式threadpoolexecutor的执行流程线程池的终止线程池的状态异步、同步1.java 线程 同步与异步线程工厂总结

java线程池

线程的缺点:

1.线程的创建它会开辟本地方法栈、jvm栈、程序计数器私有的内存,同时消耗的时候需要销毁以上三个区域,因此频繁的创建和销毁线程比较消耗系统的资源。

2.在任务量远远大于线程可以处理的任务量的时候,不能很好的拒绝任务。

所以就有了线程池:

使用池化的而技术来管理和使用线程。

线程池的优点

1.可以避免频繁的创建和销毁线程

2.可以更好的管理线程的个数和资源的个数。

3.线程池拥有更多的功能,比如线程池可以进行定时任务的执行。

4.线程池可以更友好的拒绝不能处理的任务。

线程池的6种创建方式

一共有7种创建方式

创建方式一:

创建固定个数的线程池:

package threadpooldemo;import .util.concurrent.executorservice;import java.util.concurrent.executors;/** * user:ypc; * date:2021-06-13; * time: 10:24; */public class threadpooldemo1 { public static void main(string[] args) { //创建一个固定个数的线程池 executorservice executorservice = executors.newfixedthreadpool(10); //执行任务 for (int i = 0; i < 10; i ) { executorservice.execute(new runnable() { @override public void run() { system.out.println("线程名" thread.currentthread().getname()); } }); } }}

彻底搞懂java多线程(三)

那么如果执行次数大于10次呢?

线程池不会创建新的线程,它会复用之前的线程。

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

那么如果只执行两个任务呢?它创建了是10个线程还是两个线程呢?

我们可以使用jconsole来看一看:

彻底搞懂java多线程(三)

结果是只有2个线程被创建。

创建方式二:

创建带有缓存的线程池:

适用于短期有大量的任务的时候使用

public class threadpooldemo2 { public static void main(string[] args) { //创建带缓存的线程池 executorservice executorservice = executors.newcachedthreadpool(); for (int i = 0; i < 100; i ) { executorservice.execute(new runnable() { @override public void run() { system.out.println(thread.currentthread().getname()); } }); } }}

彻底搞懂java多线程(三)

方式三:

创建执行定时任务的线程池

package threadpooldemo;import java.util.date;import java.util.concurrent.executors;import java.util.concurrent.scheduledexecutorservice;import java.util.concurrent.timeunit;/** * user:ypc; * date:2021-06-13; * time: 11:32; */public class threadpooldemo3 { public static void main(string[] args) { scheduledexecutorservice scheduledexecutorservice = executors.newscheduledthreadpool(2); system.out.println("执行定时任务前的时间:" new date()); scheduledexecutorservice.scheduleatfixedrate(new runnable() { @override public void run() { system.out.println("执行任务的时间:" new date()); } },1,2, timeunit.seconds); }}

彻底搞懂java多线程(三)

执行任务的四个参数的意义:

参数1:延迟执行的任务

参数2:延迟一段时间后执行

参数3:定时任务执行的频率

参数4:配合前两个参数使用,是2、3参数的时间单位

还有两种执行的方法:

只会执行一次的方法:

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

第三种的执行方式:

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

那么这种的执行方式和第一种的执行方式有什么区别呢?

当在两种执行的方式中分别加上sleep()之后:

彻底搞懂java多线程(三)

方式一:

彻底搞懂java多线程(三)

方式三:

彻底搞懂java多线程(三)

结论很明显了:

第一种方式是以上一个任务的开始时间 定时的时间作为当前任务的开始时间

第三种方式是以上一个任务的结束时间来作为当前任务的开始时间。

创建方式四:

package threadpooldemo;import java.util.date;import java.util.concurrent.executors;import java.util.concurrent.scheduledexecutorservice;import java.util.concurrent.timeunit;/** * user:ypc; * date:2021-06-13; * time: 12:38; */public class threadpooldemo4 { public static void main(string[] args) { //创建单个执行任务的线程池 scheduledexecutorservice scheduledexecutorservice = executors.newsinglethreadscheduledexecutor(); system.out.println("执行任务之前" new date()); scheduledexecutorservice.schedulewithfixeddelay(new runnable() { @override public void run() { system.out.println("我是singlethreadschedule" new date()); } },3,1, timeunit.seconds); }}

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

创建方式五:

创建单个线程的线程池

package threadpooldemo;import java.util.concurrent.executorservice;import java.util.concurrent.executors;/** * user:ypc; * date:2021-06-13; * time: 12:55; */public class threadpooldemo5 { public static void main(string[] args) { //创建单个线程的线程池 executorservice executorservice = executors.newsinglethreadexecutor(); for (int i = 0; i < 20; i ) { executorservice.execute(new runnable() { @override public void run() { system.out.println("线程名 " thread.currentthread().getname()); } }); } }}

彻底搞懂java多线程(三)

创建单个线程池的作用是什么?

1.可以避免频繁创建和销毁线程所带来的性能的开销

2.它有任务队列,可以存储多余的任务

3.可以更好的管理任务

4.当有大量的任务不能处理的时候,可以友好的执行拒绝策略

创建方式六:

创建异步线程池根据当前cpu来创建对应个数的线程池

package threadpooldemo;import java.util.concurrent.executorservice;import java.util.concurrent.executors;/** * user:ypc; * date:2021-06-13; * time: 13:12; */public class threadpooldemo6 { public static void main(string[] args) { executorservice executorservice = executors.newworkstealingpool(); for (int i = 0; i < 10; i ) { executorservice.execute(new runnable() { @override public void run() { system.out.println("线程名" thread.currentthread().getname()); } }); } }}

彻底搞懂java多线程(三)

运行结果为什么什么都没有呢?

看下面的异步与同步的区别就知道了。

加上这个

彻底搞懂java多线程(三)

就可以输出结果了

彻底搞懂java多线程(三)

线程池的第七种创建方式

前六种的创建方式有什么问题呢?

1.线程的数量不可控(比如带缓存的线程池)

2.工作任务量不可控(默认的任务队列的大小时integer.max_value),任务比较大肯会导致内存的溢出。

所以就可以使用下面的创建线程池的方式了:

package threadpooldemo;import java.util.concurrent.linkedblockingdeque;import java.util.concurrent.threadfactory;import java.util.concurrent.threadpoolexecutor;import java.util.concurrent.timeunit;/** * user:ypc; * date:2021-06-13; * time: 15:05; */public class threadpooldemo7 { private static int threadid = 0; public static void main(string[] args) { threadfactory threadfactory = new threadfactory() { @override public thread newthread(runnable r) { thread thread = new thread(r); thread.setname("我是threadpool-" threadid); return thread; } }; threadpoolexecutor threadpoolexecutor = new threadpoolexecutor(3, 3, 100, timeunit.milliseconds, new linkedblockingdeque<>(12), threadfactory, new threadpoolexecutor.abortpolicy()); for (int i = 0; i < 15; i ) { threadpoolexecutor.execute(new runnable() { @override public void run() { system.out.println(thread.currentthread().getname()); } }); } }}

彻底搞懂java多线程(三)

参数说明:

彻底搞懂java多线程(三)

参数一:核心线程数|线程池正常情况下的线程 数量 参数二:最大线程数|当有大量的任务的时候可以创建的最多的线程数 参数三:最大线程的存活时间 参数四:配合参数三一起使用的表示参数三的时间单位 参数五:任务队列 参数六:线程工厂 参数七:决绝策略

注意事项:最大的线程数要大于等于核心的线程数

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

五种拒绝策略

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

为什么拒绝策略可以舍弃最新的任务或者最旧的任务呢?

因为linkedblockingdeque时fifo的。

第五种:自定义的拒绝策略

彻底搞懂java多线程(三)

彻底搞懂java多线程(三)

threadpoolexecutor的执行方式

彻底搞懂java多线程(三)

package threadpooldemo;import java.util.concurrent.*;/** * user:ypc; * date:2021-06-13; * time: 16:58; */public class threadpooldemo9 { public static void main(string[] args) throws executionexception, interruptedexception { threadpoolexecutor threadpoolexecutor = new threadpoolexecutor(3, 4, 100, timeunit.milliseconds, new linkedblockingdeque<>(10), new threadpoolexecutor.discardoldestpolicy()); //线程池的执行方式一 threadpoolexecutor.execute(new runnable() { @override public void run() { system.out.println("使用了execute()执行了线程池"); } }); //线程池的执行方式二 future futuretask = threadpoolexecutor.submit(new callable() { @override public string call() throws exception { return "使用submit(new callable<>())执行了线程池"; } }); system.out.println(futuretask.get()); }}

无返回值的执行方式

彻底搞懂java多线程(三)

有返回值的执行方式

彻底搞懂java多线程(三)

threadpoolexecutor的执行流程

当任务量小于核心线程数的时候,threadpoolexecutor会创建线程来执行任务

当任务量大于核心的线程数的时候,并且没有空闲的线程时候,且当线程池的线程数小于最大线程数的时候,此时会将任务存

放到任务队列中

如果任务队列也被存满了,且最大线程数大于线程池的线程数的时候,会创建新的线程来执行任务。

如果线程池的线程数等于最大的线程数,并且任务队列也已经满了,就会执行拒绝策略。👇

彻底搞懂java多线程(三)

线程池的终止

shutdown()

线程池的任务会执行完

shutdownnow()

立即终止线程池,线程池的任务不会执行完

线程池的状态

彻底搞懂java多线程(三)

异步、同步1.java 线程 同步与异步

多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,a线程修改了b线程的处理的数据,而b线程又修改了a线程处理的数理。显然这是由于全局资源造成的,有时为了解决此问题,优先考虑使用局部变量,退而求其次使用同步代码块,出于这样的安全考虑就必须牺牲系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制

同步

a线程要请求某个资源,但是此资源正在被b线程使用中,因为同步机制存在,a线程请求不到,怎么办,a线程只能等待下去

异步

a线程要请求某个资源,但是此资源正在被b线程使用中,因为没有同步机制存在,a线程仍然请求的到,a线程无需等待同步的方式:

1.发送请求

2.等待执行完成

3.有结果的返回

异步的方式

1.发请求

2.执行完成

3.另一个线程异步处理

4.处理完成之后返回回调结果

显然,同步最最安全,最保险的。而异步不安全,容易导致死锁,这样一个线程死掉就会导致整个进程崩溃,使用异步的机制,性能会有所提升

线程工厂

设想这样一种场景,我们需要一个线程池,并且对于线程池中的线程对象,赋予统一的线程优先级、统一的名称、甚至进行统一的业务处理或和业务方面的初始化工作,这时工厂方法就是最好用的方法了

package threadpooldemo;import java.util.concurrent.executorservice;import java.util.concurrent.executors;import java.util.concurrent.threadfactory;/** * user:ypc; * date:2021-06-13; * time: 11:12; */public class threadfactorydemo { public static void main(string[] args) { mythreadfactory mythreadfactory = new mythreadfactory(); executorservice executorservice = executors.newfixedthreadpool(10,mythreadfactory); for (int i = 0; i < 10; i ) { executorservice.execute(new runnable() { @override public void run() { system.out.println("使用线程工厂设置的线程名:" thread.currentthread().getname() " 使用线程工厂设置的线程的优先级" thread.currentthread().getpriority()); } }); } } private static int count = 0; static class mythreadfactory implements threadfactory{ @override public thread newthread(runnable r) { thread thread = new thread(r); thread.setpriority(8); thread.setname("thread--" count ); return thread; } }}

彻底搞懂java多线程(三)

总结

本篇文章就到这里了,希望可以对你有所帮助,也希望您能够多多关注软科小院的更多内容!

网友评论
评论
更多编程技术
  • 编程技术推荐
更多
最新软件下载
网站地图