前面几篇博文基本上总结了一下java并发里的一些内容,这篇博文主要从一个问题入手,看看都能用到前面总结的哪些并发技术去解决。
题目描述:
模拟一个场景:处理16条日志记录,每条日志记录打印时间需要1秒,正常情况下如果将这16条记录去部打完需要16秒,现在为了提高效率,准备开启4个线程去打印,4秒钟打印完,实现这个demo。
先来分析一下这个题目,关于这16条日志记录,我们可以在主线程中产生出来,这没用什么难度,关键是开启4个线程去执行,现在有两种思路:一种是日志的产生和打印日志的线程在逻辑上分开;一种是日志的产生和打印日志的线程在逻辑上不是分开的。这样说可能有点晦涩,下面我针对这两种思路,写个实现的demo就好理解了。
思路一
日志产生和日志打印在逻辑上是分开的。
这相当于两条战线: 一条战线在不停的产生日志,另一个战线在不停的打印日志。很明显会想到阻塞队列的使用,产生日志不停的往阻塞队列中塞,打印日志不停的从阻塞队列中取,阻塞队列的大小可以自己设置,可以设置16个,也可以设置为1个,这都不影响执行。所以会用到BlockingQueue,下面看一下实现的demo:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
public class Practice1 {
public static void main(String[] args) {
//定义一个阻塞队列,队列大小可以装16个信息
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(16);
for (int i = 0; i < 4; i ++) {
//开启四个线程去阻塞队列中取日志打印
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
String log = queue.take();
//取日志
parseLog(log);
//打印日志
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
).start();
}
System.out.println("begin:" + (System.currentTimeMillis()/1000));
for (int i = 0; i < 16; i ++) {
final String log = "" + (i+1);
//表示一个日志
try {
queue.put(log);
//将产生的日志塞到阻塞队列中去
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void parseLog(String log) {
//打印日志的方法
System.out.println(Thread.currentThread().getName() + "---"
+ log + "---" + (System.currentTimeMillis()/1000));
try {
Thread.sleep(1000);
//模拟打印一次日志需要1秒
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
|
这就好比一个系统正在运作,一边不停的产生日志,一边在不停的开启多个线程去打印日志信息,这个demo就写好了,运行结果就不贴了。
思路二
日志产生和日志打印在逻辑上不是分开的。
这种思路就是,我产生日志的同时,你就给我打印出来,四个线程一起干!那么这种思路的话,就得用到线程池了,我一开始创建一个线程池,里面装了4个线程,然后产生日志的时候,我让这个线程池拿线程去执行它即可。demo如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public class Practice1 {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(4);
//创建一个线程池
System.out.println("begin:" + (System.currentTimeMillis()/1000));
for (int i = 0; i < 16; i ++) {
final String log = "" + (i+1);
//表示一个日志
service.execute(new Runnable() {
//拿一个线程去执行
@Override
public void run() {
parseLog(log);
}
}
);
}
service.shutdown();
//最后别忘了关掉线程池
}
public static void parseLog(String log) {
System.out.println(Thread.currentThread().getName() + "---"
+ log + "---" + (System.currentTimeMillis()/1000));
try {
Thread.sleep(1000);
//模拟打印一次日志需要1秒
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
|
关于这个问题,就总结到这吧,把这两种思路搞清楚一般就可以有效的解决了。
总结
以上就是本文关于Java编程一道多线程问题实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/eson_15/article/details/51593139
相关文章
- ASP.NET本地开发时常见的配置错误及解决方法? 2025-06-10
- ASP.NET自助建站系统的数据库备份与恢复操作指南 2025-06-10
- 个人网站服务器域名解析设置指南:从购买到绑定全流程 2025-06-10
- 个人网站搭建:如何挑选具有弹性扩展能力的服务器? 2025-06-10
- 个人服务器网站搭建:如何选择适合自己的建站程序或框架? 2025-06-10
- 2025-07-10 怎样使用阿里云的安全工具进行服务器漏洞扫描和修复?
- 2025-07-10 怎样使用命令行工具优化Linux云服务器的Ping性能?
- 2025-07-10 怎样使用Xshell连接华为云服务器,实现高效远程管理?
- 2025-07-10 怎样利用云服务器D盘搭建稳定、高效的网站托管环境?
- 2025-07-10 怎样使用阿里云的安全组功能来增强服务器防火墙的安全性?
快网idc优惠网
QQ交流群
-
2025-05-27 61
-
2025-05-27 50
-
2025-05-29 26
-
2025-05-27 53
-
详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失
2025-05-29 60

