Browsed by
标签:多线程

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
72 views
Netty : what’s it

Netty : what’s it

Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.

 

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.

‘Quick and easy’ doesn’t mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.

Features

Design

  • Unified API for various transport types – blocking and non-blocking socket
  • Based on a flexible and extensible event model which allows clear separation of concerns
  • Highly customizable thread model – single thread, one or more thread pools such as SEDA
  • True connectionless datagram socket support (since 3.1)

Ease of use

  • Well-documented Javadoc, user guide and examples
  • No additional dependencies, JDK 5 (Netty 3.x) or 6 (Netty 4.x) is enough
    • Note: Some components such as HTTP/2 might have more requirements. Please refer to the Requirements page for more information.

Performance

  • Better throughput, lower latency
  • Less resource consumption
  • Minimized unnecessary memory copy

Security

  • Complete SSL/TLS and StartTLS support

Community

  • Release early, release often
  • The author has been writing similar frameworks since 2003 and he still finds your feed back precious!

来源: Netty: Home

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
309 views
让大家在InfoQ上听见你的声音

让大家在InfoQ上听见你的声音

投稿

InfoQ由社区推动,这里的内容源自像你一样的专业技术人。对于社区而言,你是最重要的。

你是否热衷于软件开发?你是否热衷于与他人分享你的知识与经验?InfoQ一直在寻找优秀的作者与热情的编辑加入我们的内容贡献队伍中,跟社区里的其他成员一起,促进软件开发领域知识与创新的传播。

为InfoQ贡献内容的方式有两种,联系方式均为editors@cn.infoq.com:

深度文章投稿

深度文章不是简单的How-to。
作者需要对某个领域有十分深入的理解,
或非常丰富的实战经验。
详情见InfoQ中文站投稿须知

成为社区编辑

InfoQ社区编辑能够在自己关注的领域挖掘热点新闻和人物,并直观的将事实表述出来分享给读者。社区编辑分为翻译组、原创新闻组、专家审校组等,详见:
InfoQ编辑团队加盟指南

InfoQ编辑的核心价值观

InfoQ.com是由实践者驱动的社区媒体,我们的目标是: 推进和传播软件开发领域的知识和创新。 作为编辑兼实践者,我们参与成员驱动的编辑过程,向着这个共同目标努力前进,具体工作方式包括:翻译和撰写新闻,并以文章、采访、录制技术大会视频等多种形式分享知识。

我们恪守并践行下列核心价值观:

做信息的罗宾汉。我们的主要职能就是从少数拥有信息的精英那里寻找信息,并将其发布给广大群众。当我们发现一些很棒的信息,并且认为值得让整个社区知道时,我们应该将发布它视为我们必须承担的职责。

做最好的,而不是最快的。我们不是发布突发新闻的网站,当某件事情发生后,过上几天再发布也是可以的,只要我们收集到足够的材料,并能提供更深度的内容。

做推进者,而不是领导者。我们会编写各种内容,展现社区中的新人老将、各种活动、各种想法,以此推进社区的成长,而不是关注我们自己。作为推进者,我们与社区协作,产生有价值的内容,而不是只考虑推行我们的想法;我们能够而且应该辅助现有的各种业界活动和趋势。

提供可信赖的内容。我们的内容将会不带偏见,不会偏向个人或是厂商,除非能够明确表明属于某种“意见”。用户可以期望InfoQ的内容有所裨益,而且源于事实。我们努力坚持媒体工作的原则,并体现在我们的新闻写作活动中,同时也要认识到:我们不是全职的权威媒体工作者,而是试图做正确之事的实践者。

来源: 让大家在InfoQ上听见你的声音

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
363 views
疫苗:Java HashMap的死循环 | | 酷 壳 – CoolShell

疫苗:Java HashMap的死循环 | | 酷 壳 – CoolShell

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在 Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历过,本来觉得没什么好写的,因为 Java的HashMap是非线程安全的,所以在并发下必然出现问题。但是,我发现近几年,很多人都经历过这个事(在网上查“HashMap Infinite Loop”可以看到很多人都在说这个事)所以,觉得这个是个普遍问题,需要写篇疫苗文章说一下这个事,并且给大家看看一个完美的“Race Condition”是怎么形成的。 问题的症状 从前我们的 Java代码因为一些原因使用了HashMap这个东西,但是当时的程序是单线程的,一切都没有问题。后来,我们的程序性能有问题,所以需要变成多线程的,于是,变成多线程后到了线上,发现程序经常占了100%的CPU,查看堆栈,你会发现程序都Hang在了HashMap.get()这个方法上了,重启程序后问题消失。但是过段时间又会来。而且,这个问题在测试环境里可能很难重现。 我们简单的看一下我们自己的代码,我们就知道HashMap被多个线程操作。而 Java的文档说HashMap是非线程安全的,应该用ConcurrentHashMap。 但是在这里我们可以来研究一下原因。 Hash表数据结构 我需要简单地说一下HashMap这个经典的数据结构。 HashMap通常会用一个指针数组(假设为table中,如果有两个不同的key被算在了同一个i,那么就叫冲突,又叫碰撞,这样会在table上形成一个链表。 我们知道,如果tablepublic V put(K key, V value) { …… //算Hash值 int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); //如果该key已被插入,则替换掉旧的value (链接操作) for (Entry e = table; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V

来源: 疫苗: Java HashMap的死循环 | | 酷 壳 – CoolShell

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
100 views
模拟HashMap死循环现象 – madding.lip – 博客频道 – CSDN.NET

模拟HashMap死循环现象 – madding.lip – 博客频道 – CSDN.NET

Java中有一个HashMap,我们也都知道,改类型为线程不安全,会出现线程死循环问题,今天我们通过一个小代码来模拟一下HashMap产生死循环,同时描述一下现象: 代码: java代码:package com.wmmad.threadlocal.test;import java.util.HashMap;/** * * @author madding.lip *

来源: 模拟HashMap死循环现象 – madding.lip – 博客频道 – CSDN.NET

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
371 views
三个实例演示 Java Thread Dump 日志分析

三个实例演示 Java Thread Dump 日志分析

jstack Dump 日志文件中的线程状态
dump 文件里,值得关注的线程状态有:
  1. 死锁,Deadlock(重点关注) 
  2. 执行中,Runnable   
  3. 等待资源,Waiting on condition(重点关注) 
  4. 等待获取监视器,Waiting on monitor entry(重点关注)
  5. 暂停,Suspended
  6. 对象等待中,Object.wait() 或 TIMED_WAITING
  7. 阻塞,Blocked(重点关注)  
  8. 停止,Parked

下面我们先从第一个例子开始分析,然后再列出不同线程状态的含义以及注意事项,最后再补充两个实例。

综合示范一:Waiting to lock 和 Blocked
实例如下:
“RMI TCP Connection(267865)-172.16.5.25” daemon prio=10 tid=0x00007fd508371000 nid=0x55ae waiting for monitor entry [0x00007fd4f8684000]
    java.lang.Thread.State: BLOCKED (on object monitor)
at org.apache.log4j.Category.callAppenders(Category. java:201)
waiting to lock (a org.apache.log4j.Logger)
at org.apache.log4j.Category.forcedLog(Category. java:388)
at org.apache.log4j.Category.log(Category. java:853)
at org.apache.commons.logging.impl.Log4JLogger.warn(Log4JLogger. java:234)
at com.tuan.core.common.lang.cache.remote.SpyMemcachedClient.get(SpyMemcachedClient. java:110)
……
1)线程状态是 Blocked,阻塞状态。说明线程等待资源超时!
2)“ waiting to lock ”指,线程在等待给这个 0x00000000acf4d0c0 地址上锁(英文可描述为:trying to obtain  0x00000000acf4d0c0 lock)。
3)在 dump 日志里查找字符串 0x00000000acf4d0c0,发现有大量线程都在等待给这个地址上锁。如果能在日志里找到谁获得了这个锁(如locked ),就可以顺藤摸瓜了。
4)“waiting for monitor entry”说明此线程通过 synchronized(obj) {……} 申请进入了临界区,从而进入了下图1中的“Entry Set”队列,但该 obj 对应的 monitor 被其他线程拥有,所以本线程在 Entry Set 队列中等待。
5)第一行里,”RMI TCP Connection(267865)-172.16.5.25″是 Thread Name 。tid指 Java Thread id。nid指native线程的id。prio是线程优先级。[0x00007fd4f8684000]是线程栈起始地址。
Dump文件中的线程状态含义及注意事项

含义如下所示:

  • Deadlock:死锁线程,一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。
  • Runnable:一般指该线程正在执行状态中,该线程占用了资源,正在处理某个请求,有可能正在传递SQL到数据库执行,有可能在对某个文件操作,有可能进行数据类型等转换。
  • Waiting on condition:等待资源,或等待某个条件的发生。具体原因需结合 stacktrace来分析。
    • 如果堆栈信息明确是应用代码,则证明该线程正在等待资源。一般是大量读取某资源,且该资源采用了资源锁的情况下,线程进入等待状态,等待资源的读取。
    • 又或者,正在等待其他线程的执行等。
    • 如果发现有大量的线程都在处在 Wait on condition,从线程 stack看,正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。
      • 一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;
      • 另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。
    • 另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。
  • Blocked:线程阻塞,是指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。
  • Waiting for monitor entry 和 in Object.wait():Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。从下图1中可以看出,每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”,而在 “Wait Set”中等待的线程状态是 “in Object.wait()”。

 

图1 A Java Monitor

 

综合示范二:Waiting on condition 和 TIMED_WAITING
实例如下:
“RMI TCP Connection(idle)” daemon prio=10 tid=0x00007fd50834e800 nid=0x56b2 waiting on condition [0x00007fd4f1a59000]
    java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
parking to wait for   (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport. java:198)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue. java:424)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue. java:323)
at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue. java:874)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor. java:945)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor. java:907)
at java.lang.Thread.run(Thread. java:662)
1)“TIMED_WAITING (parking)”中的 timed_waiting 指等待状态,但这里指定了时间,到达指定的时间后自动退出等待状态;parking指线程处于挂起中。
2)“waiting on condition”需要与堆栈中的“parking to wait for   (a java.util.concurrent.SynchronousQueue$TransferStack)”结合来看。首先,本线程肯定是在等待某个条件的发生,来把自己唤醒。其次,SynchronousQueue 并不是一个队列,只是线程之间移交信息的机制,当我们把一个元素放入到 SynchronousQueue 中时必须有另一个线程正在等待接受移交的任务,因此这就是本线程在等待的条件。
3)别的就看不出来了。

综合示范三:in Obejct.wait() 和 TIMED_WAITING

实例如下:
“RMI RenewClean-[172.16.5.19:28475]” daemon prio=10 tid=0x0000000041428800 nid=0xb09 in Object.wait() [0x00007f34f4bd0000]
    java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
waiting on (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue. java:118)
locked (a java.lang.ref.ReferenceQueue$Lock)
at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient. java:516)
at java.lang.Thread.run(Thread. java:662)

1)“TIMED_WAITING (on object monitor)”,对于本例而言,是因为本线程调用了  java.lang.Object.wait(long timeout) 而进入等待状态。

2)“Wait Set”中等待的线程状态就是“ in Object.wait() ”。当线程获得了 Monitor,进入了临界区之后,如果发现线程继续运行的条件没有满足,它则调用对象(一般就是被 synchronized 的对象)的 wait() 方法,放弃了 Monitor,进入 “Wait Set”队列。只有当别的线程在该对象上调用了 notify() 或者 notifyAll() ,“ Wait Set”队列中线程才得到机会去竞争,但是只有一个线程获得对象的 Monitor,恢复到运行态。

3)RMI RenewClean 是 DGCClient 的一部分。DGC 指的是 Distributed GC,即分布式垃圾回收。

4)请注意,是先 locked ,后 waiting on ,之所以先锁再等同一个对象,请看下面它的代码实现:
static private class  Lock { };
private Lock lock = new Lock();
public Reference extends T> remove(long timeout)
{
    synchronized (lock) {
        Reference extends T> r = reallyPoll();
        if (r != nullreturn r;
        for (;;) {
            .wait(timeout);
            r = reallyPoll();
            ……
       }
}
即,线程的执行中,先用 synchronized 获得了这个对象的 Monitor(对应于  locked  );当执行到 lock.wait(timeout);,线程就放弃了 Monitor 的所有权,进入“Wait Set”队列(对应于  waiting on  )。
5)从堆栈信息看,是正在清理 remote references to remote objects ,引用的租约到了,分布式垃圾回收在逐一清理呢。

 

参考资源:
1)CUBRID,2012,How to Analyze Java Thread Dumps;
2)iteye,2012,虚拟机stack全分析
3)iteye,2008,如何分析 Java虚拟机死锁;
4)csdn,2012, java stack dump中JVM运行过程中产生的一些常见线程介绍和解释;
5)2009, Java线程dump的分析;
6)jiacheo,2012,tomcat thread dump 分析
from:
http://www.cnblogs.com/zhengyun_ustc/archive/2013/01/06/dumpanalysis.html
-end-
跳至工具栏