大家用java多线程做什么?

miracleliu 2014-01-07 02:35:02

工作基本不用多线程,想了解大家用多线程干嘛?

比如: 处理大文件,多个线程共同处理可能会快点。

还有什么情况需要多线程?

...全文
15413 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
在键盘上跳舞 2016-04-19
  • 打赏
  • 举报
回复
推荐文章:JAVA多线程系列(J.U.C)-整体技术栈:http://www.haonanji.cn/347.html
tracyliang223 2015-08-24
  • 打赏
  • 举报
回复
15楼大神 厉害!可惜新手看不懂
liliangdc 2014-01-20
  • 打赏
  • 举报
回复
多线程最多的场景:web服务器本身;各种专用服务器(如游戏服务器); 多线程的常见应用场景: 1、后台任务,例如:定时向大量(100w以上)的用户发送邮件; 2、异步处理,例如:发微博、记录日志等; 3、分布式计算
kakashi8841 2014-01-19
  • 打赏
  • 举报
回复
多线程使用的主要目的在于: 1、吞吐量:你做WEB,容器帮你做了多线程,但是他只能帮你做请求层面的。简单的说,可能就是一个请求一个线程。或多个请求一个线程。如果是单线程,那同时只能处理一个用户的请求。 2、伸缩性:也就是说,你可以通过增加CPU核数来提升性能。如果是单线程,那程序执行到死也就利用了单核,肯定没办法通过增加CPU核数来提升性能。 鉴于你是做WEB的,第1点可能你几乎不涉及。那这里我就讲第二点吧。 --举个简单的例子: 假设有个请求,这个请求服务端的处理需要执行3个很缓慢的IO操作(比如数据库查询或文件查询),那么正常的顺序可能是(括号里面代表执行时间): a、读取文件1 (10ms) b、处理1的数据(1ms) c、读取文件2 (10ms) d、处理2的数据(1ms) e、读取文件3 (10ms) f、处理3的数据(1ms) g、整合1、2、3的数据结果 (1ms) 单线程总共就需要34ms。 那如果你在这个请求内,把ab、cd、ef分别分给3个线程去做,就只需要12ms了。 所以多线程不是没怎么用,而是,你平常要善于发现一些可优化的点。然后评估方案是否应该使用。 假设还是上面那个相同的问题:但是每个步骤的执行时间不一样了。 a、读取文件1 (1ms) b、处理1的数据(1ms) c、读取文件2 (1ms) d、处理2的数据(1ms) e、读取文件3 (28ms) f、处理3的数据(1ms) g、整合1、2、3的数据结果 (1ms) 单线程总共就需要34ms。 如果还是按上面的划分方案(上面方案和木桶原理一样,耗时取决于最慢的那个线程的执行速度),在这个例子中是第三个线程,执行29ms。那么最后这个请求耗时是30ms。比起不用单线程,就节省了4ms。但是有可能线程调度切换也要花费个1、2ms。因此,这个方案显得优势就不明显了,还带来程序复杂度提升。不太值得。 那么现在优化的点,就不是第一个例子那样的任务分割多线程完成。而是优化文件3的读取速度。 可能是采用缓存和减少一些重复读取。 首先,假设有一种情况,所有用户都请求这个请求,那其实相当于所有用户都需要读取文件3。那你想想,100个人进行了这个请求,相当于你花在读取这个文件上的时间就是28×100=2800ms了。那么,如果你把文件缓存起来,那只要第一个用户的请求读取了,第二个用户不需要读取了,从内存取是很快速的,可能1ms都不到。 伪代码:

public class MyServlet extends Servlet{
    private static Map<String, String> fileName2Data = new HashMap<String, String>();
    private void processFile3(String fName){
        String data = fileName2Data.get(fName);
        if(data==null){
            data = readFromFile(fName);    //耗时28ms
            fileName2Data.put(fName, data);
        }
        //process with data
    }
}
看起来好像还不错,建立一个文件名和文件数据的映射。如果读取一个map中已经存在的数据,那么就不不用读取文件了。 可是问题在于,Servlet是并发,上面会导致一个很严重的问题,死循环。因为,HashMap在并发修改的时候,可能是导致循环链表的构成!!!(具体你可以自行阅读HashMap源码)如果你没接触过多线程,可能到时候发现服务器没请求也巨卡,也不知道什么情况! 好的,那就用ConcurrentHashMap,正如他的名字一样,他是一个线程安全的HashMap,这样能轻松解决问题。

public class MyServlet extends Servlet{
    private static ConcurrentHashMap<String, String> fileName2Data = new ConcurrentHashMap<String, String>();
    private void processFile3(String fName){
        String data = fileName2Data.get(fName);
        if(data==null){
            data = readFromFile(fName);    //耗时28ms
            fileName2Data.put(fName, data);
        }
        //process with data
    }
}
这样真的解决问题了吗,这样虽然只要有用户访问过文件a,那另一个用户想访问文件a,也会从fileName2Data中拿数据,然后也不会引起死循环。 可是,如果你觉得这样就已经完了,那你把多线程也想的太简单了,骚年! 你会发现,1000个用户首次访问同一个文件的时候,居然读取了1000次文件(这是最极端的,可能只有几百)。What the fuckin hell!!! 难道代码错了吗,难道我就这样过我的一生! 好好分析下。Servlet是多线程的,那么

public class MyServlet extends Servlet{
    private static ConcurrentHashMap<String, String> fileName2Data = new ConcurrentHashMap<String, String>();
    private void processFile3(String fName){
        String data = fileName2Data.get(fName);
        //“偶然”-- 1000个线程同时到这里,同时发现data为null
        if(data==null){
            data = readFromFile(fName);    //耗时28ms
            fileName2Data.put(fName, data);
        }
        //process with data
    }
}
上面注释的“偶然”,这是完全有可能的,因此,这样做还是有问题。 因此,可以自己简单的封装一个任务来处理。

public class MyServlet extends Servlet{
    private static ConcurrentHashMap<String, FutureTask> fileName2Data = new ConcurrentHashMap<String, FutureTask>();
    private static ExecutorService exec = Executors.newCacheThreadPool();
    private void processFile3(String fName){
        FutureTask data = fileName2Data.get(fName);
        //“偶然”-- 1000个线程同时到这里,同时发现data为null
        if(data==null){
            data = newFutureTask(fName);
            FutureTask old = fileName2Data.putIfAbsent(fName, data);
            if(old==null){
                data = old;
            }else{
                exec.execute(data);
            }
        }
        String d = data.get();
        //process with data
    }
    
    private FutureTask newFutureTask(final String file){
        return  new FutureTask(new Callable<String>(){
            public String call(){
                return readFromFile(file);
            }

            private String readFromFile(String file){return "";}
        }
    }
}
以上所有代码都是直接在bbs打出来的,不保证可以直接运行。
梦入神经 2014-01-18
  • 打赏
  • 举报
回复
web处理请求就是多线程,都已经封装好了
l107868382 2014-01-17
  • 打赏
  • 举报
回复
加快运算速度。
-阿克蒙德- 2014-01-08
  • 打赏
  • 举报
回复
引用 8 楼 miraclestar 的回复:
嗯,差不多这个意思。 现在想做的 是提高web的性能,打算单开几个线程做数据库操作,应该会快不少。 想知道还有其他,我不知道的,多线程的好用法没?
想要提高性能的话,通过存储过程解决吧,把部分增删改查操作写成存储过程,会快好多
sjlzcj 2014-01-07
  • 打赏
  • 举报
回复
各种异步处理
简易人 2014-01-07
  • 打赏
  • 举报
回复
兄弟,直白一点说。就类似银行的柜台,如果只开通一个柜台的话,其他人的都会在一个柜台等下去,一个一个的,等着处理,但是如果银行柜台同时开通5个(类似于5个线程)那么只要有一个柜台空闲,你就可以直接过去处理事情,而不用一直等待着。
长笛党希望 2014-01-07
  • 打赏
  • 举报
回复
多线程对于web应用中不多,大多都是封装好了的,除了偶尔用多线程操作文件之类,其他真没用到。。。
miracleliu 2014-01-07
  • 打赏
  • 举报
回复
引用 7 楼 u012047741 的回复:
我了解你的迷惑,我以前也这般迷惑过 其实你要想用,好多地方都能用上,我觉得“统计分析”这种就可以,让每个线程去统计一个部门的某类信息 当然web程序应用的不多,如果你想找个简单的方式确实感受下,可以看看窗体那块
嗯,差不多这个意思。 现在想做的 是提高web的性能,打算单开几个线程做数据库操作,应该会快不少。 想知道还有其他,我不知道的,多线程的好用法没?
-阿克蒙德- 2014-01-07
  • 打赏
  • 举报
回复
我了解你的迷惑,我以前也这般迷惑过 其实你要想用,好多地方都能用上,我觉得“统计分析”这种就可以,让每个线程去统计一个部门的某类信息 当然web程序应用的不多,如果你想找个简单的方式确实感受下,可以看看窗体那块
  • 打赏
  • 举报
回复
那你问多线程的场景有什么用呢,对你又不适用
  • 打赏
  • 举报
回复
引用 4 楼 miraclestar 的回复:
[quote=引用 3 楼 lwb314 的回复:] 场景太多了,有哪些程序不是多线程的呢?你现在写WEB是中间件帮你完成了线程的控制,其实基本所有软件都需要用到多线程,你用的开发工具,浏览器,数据库,不都是嘛,所以这个问题没法回答。
这个当然知道。可是我不写这些现成的东西。[/quote]你要写的东西,你自己不知道应不应该用多线程?是这个问题吗?
miracleliu 2014-01-07
  • 打赏
  • 举报
回复
引用 3 楼 lwb314 的回复:
场景太多了,有哪些程序不是多线程的呢?你现在写WEB是中间件帮你完成了线程的控制,其实基本所有软件都需要用到多线程,你用的开发工具,浏览器,数据库,不都是嘛,所以这个问题没法回答。
这个当然知道。可是我不写这些现成的东西。
  • 打赏
  • 举报
回复
场景太多了,有哪些程序不是多线程的呢?你现在写WEB是中间件帮你完成了线程的控制,其实基本所有软件都需要用到多线程,你用的开发工具,浏览器,数据库,不都是嘛,所以这个问题没法回答。
Fish-- 2014-01-07
  • 打赏
  • 举报
回复
多线程跟马路多车道差不多一个意思,多车道通车就多点。 常见场景就是操作系统、WEB服务、FTP下载等等
快乐的小呆 2014-01-07
  • 打赏
  • 举报
回复
都没怎么用过,坐等大神解释

50,530

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧