用Java实现多线程有哪些途径?

创建一个 Thread 子类:TestThread 并重写 run()。
实现Runnable接口:TestRunnable,实现run()。
实用提醒:优先实现Runnable接口,因为它更灵活并且避免了继承的限制。

Java多线程之ThreadPoolExecutor原理(图文代码实例详解)

哎,我告诉你,ThreadPoolExecutor,我以前在做项目的时候遇到过很多坑。
记得当时在杭州项目紧急启动,被迫系统地解决Java多线程。

我们先来说说厂家。
面试官最喜欢测试的就是这7 个参数。
corePoolSize是核心线程的数量,即使空闲也必须保留,除非你将consentCoreThreadTimeOut设置为true。
maximPoolSize是最大线程数,keepAliveTime是线程的空闲生存时间,unit是时间单位,workQueue是任务队列,threadFactory是创建线程的工厂,RejectedExecutionHandler是拒绝策略。

所以面试官也喜欢问ctl变量。
这件事是相当复杂的。
高3 位表示状态,低2 9 位表示线程数,线程数最大容量为(2 ^2 9 )-1 有几种状态:RUNNING、SHUTDOWN、STOP、TIDYING 和 TERMINATED。

提交任务执行过程,主要通过执行或者调度的方式。
execute返回void,send返回Future,是一个异步操作。
执行过程为:
1 .如果正在运行的线程数小于主线程数,请尝试启动新线程。
2 . 如果任务能够成功添加到队列中,则需要再次检查状态。
如果线程池已经关闭,任务将被恢复到队列中。
3 . 如果加入队列失败,请尝试添加新线程。
如果这也失败,您就知道线程池已关闭或饱和并运行拒绝策略。

添加新工作线程的过程主要是通过addWorker方法完成的。
这里有很多细节,比如检查线程池状态、队列是否为空、线程数是否超过限制等。
创建Worker对象,然后获取mainLock,然后检查状态,最后启动Worker线程。

Worker运行进程,实现Runnable接口,run方法会调用runWorker。
这里有一个循环不断地获取任务并执行它们。
如果无法获取任务,则处理退出逻辑。

如果 getTask 方法返回 null,则处理 Worker 输出。
这里还有很多细节,比如线程池状态、线程数量、超时等。

worker 退出处理。
如果任务运行时发生错误,线程数就会减少。
然后获取mainLock,完成任务计数,移除worker,尝试关闭线程池,根据状态补充非主线程。

这个源代码看起来很复杂,尤其是ctl变量。
我是读了又读之后才明白的。
记得有一次在一个项目中,因为没有关注ctl变量的状态,提前关闭了线程池,差点引发了很大的错误。
所以,你不能只读一遍这个东西,你必须练习和尝试。

java框架中如何处理并发和多线程?

Java并发多线程是提高性能的关键。

1 . 线程池:复用线程以减少开销,使用ExecutorService或Spring的ThreadPoolTask​​Executor。
2 、锁同步:为了保护资源安全,可以使用synchronized或者ReentrantLock。
3 .并行流:分割任务,自动多线程,但避免修改共享变量。
4 .异步编程:非阻塞,使用CompletableFuture、Spring的@Async。
5 、实战:例如Spring异步邮件发送、配置线程池、处理异常等。
6 . 高级工具:CountDownLatch、CyclicBarrier、BlockingQueue、ConcurrentHashMap。

选择正确的工具来构建高效的并发应用程序。
看看你自己,有什么挑战?

面试官:公司项目中Java的多线程一般用在哪些场景?

说实话,如果正确使用Java多线程,系统性能其实是可以提高的。
就说几个我见过的例子吧。

1 .请求高并发 我之前做的一个电商项目,双十一期间单单Tomcat就处理了8 000个并发请求。
那时候还没有添加多线程,就卡住了。
修改完之后我立马就跑了。
即用户传输文件,分配一个线程来存储文件。
主线程不必等待,继续处理其他请求。
这一招用得顺手,就能被阿里的双1 1 体系反制。

2 异步任务处理 我记得我在做用户注册功能的时候,发送确认邮件花了很长时间。
后来开辟了一个单独的线程用于发送电子邮件,用户点击注册按钮后立即被重定向,无需等待。
此操作特别适合后台任务,例如凌晨三点备份数据。

3 优化 I/O 密集型操作 我有一个游戏服务器项目,数据库查询非常慢。
切换到多线程后,5 个表查询分别在5 个线程中执行,总时间从3 4 ms减少到1 2 ms。
这个方法在数据处理中特别有用,我后来在大数据分析中也用到了这个思想。

4 资源隔离和优先级控制 之前做支付系统的时候,我发现生成报告实际上会减慢支付的速度。
后来又创建了两个线程池,支付线程池和报表线程池明确分开。
这个技巧在混合任务中特别实用,应该在淘宝这样的场景中进行。

5 复杂的计算问题 有一天,我在渲染图像时,我的CPU直接烧坏了。
后来,矩阵被分成块,六个核心同时推出。
结果快了十倍。
对于此类资源密集型任务,多线程简直就是神器。

6 计划任务和周期性操作 我们的系统有一个数据同步任务,每天早上都会同步。
使用 ScheduledExecutorService 使其非常顺利,并且完全忽略主线程。
每5 分钟运行一次,比cron更准时。

7 分布式计算平台 后来转做大数据,Hadoop分布式计算特别依赖多线程。
例如,在Spark中,Executor进程中使用多个线程并行处理分区数据,集群的吞吐量直接翻倍。

但是您应该注意一些陷阱: 1 .线程安全。
当我使用 HashMap 时,它立即崩溃了。
我改用ConcurrentHashMap来稳定它。
2 、不要盲目制造话题。
某些操作(例如顺序 I/O)会更慢。
3 .如果线程池没有正确使用,则无用。
我记得有一个项目使用了 5 0 个线程并冻结了。
后来改成2 0就好了。

FileCacheServlet的例子很经典。
Future 和 ConcurrentHashMap 的结合特别巧妙,避免了文件重新读取并使其线程安全。
说实话,多线程的本质正是这几个字:异步、并行,不过要看场景。