Java线程的使用技巧

Java线程的一些实用技巧


一、线程名(事务ID)

线程设置线程名称,更容易问题的跟踪,如果增加事务ID,更方便问题的排查。

通过 Jstack  :java虚拟机自带的一种堆栈跟踪工具。

收集thread dump 文件

jstack pid > xxxxfile

jstack Dump 日志文件中的线程状态

dump 文件里,值得关注的线程状态有:

1、死锁,Deadlock(重点关注) 

2、执行中,Runnable   

3、等待资源,Waiting on (重点关注) 

4、等待获取监视器,Waiting on monitor entry(重点关注)

5、暂停,Suspended

6、对象等待中,Object.wait() 或 TIMED_WAITING

7、阻塞,Blocked(重点关注)  

8、停止,Parked


二、线程本地存储(ThreadLocal)

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。


三、线程优先级(核心业务,后台服务)

1、记住当线程的优先级没有指定时,所有线程都携带普通优先级。

2、优先级可以用从1到10的范围指定。10表示最高优先级,1表示最低优先级,5是普通优先级。

3、记住优先级最高的线程在执行时被给予优先。但是不能保证线程在启动时就进入运行状态。

4、与在线程池中等待运行机会的线程相比,当前正在运行的线程可能总是拥有更高的优先级。

5、由调度程序决定哪一个线程被执行。

6、t.setPriority()用来设定线程的优先级。

7、记住在线程开始方法被调用之前,线程的优先级应该被设定。

8、你可以使用常量,如MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY来设定优先级。


四、守护线程&用户线程

Java中有两种线程:User Thread 和 Daemon Thread

守护线程是一种后台提供通用服务的线程,如GC,只有当所有的用户线程都结束,守护进程没有守护对象才会随JVM结束工作。

守护线程和用户线程几乎没有区别,唯一的不同之处在于虚拟机的离开,当所有的用户线程退出,守护进程才会跟随JVM退出。因为没有被守护者,守护进程也就没有工作可做了,也就没有继续运行的必要了。

实际应用中的列子:

在使用长连接的comet服务端推送技术中,消息推送线程设置为守护进程,服务于ChatServlet的servlet用户线程,在servlet的init启动消息线程,servlet一旦初始化后,一直存在服务器,servlet摧毁后,消息线程自动退出。

容器收到一个Servlet请求,调度线程从线程池中选出一个工作线程,将请求传递个该工作者线程,然后又该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另外一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个Servlet。当容器同时收到对同一个Servlet的多个请求的时候,那么这个servlet的service方法将在多线程中并发执行。

servlet容器默认采用单实例的方式来处理请求,这样减少产生Servlet实例的开销,提升了对请求的响应时间,对于Tomcat可以在server.xml中通过元素设置线程池中线程的数目。

Tomcat 线程分配

五、处理器亲和性

(靠近硬件,进程绑定到特定的CPU核心上+优先级)

1、数据的运用概率提高,数据在CPU缓存上,不需要再去内存进行加载。

2、同时减少线程切换CPU的几率。

效率提升并不会太明显,但是吞吐量会相对趋向稳定。非常适合低延迟的网络应用,如netty

如何绑定:

liunx -> 命令(taskset)把进程绑定到特定的CPU上

taskset -c 1 “Java AboutToBepuned”

通过Java-Thread-Affinity库实现线程绑定CPU


JAVA并发的基本家族成员


Synchronized:锁关键字

Synchronized获得锁,releasing lock 释放锁,thread.interrupt 中断机制(stop()、interrupted()、isInterrupted())、wait、notify、notifyAll

Synchronized 锁机制,synchronized是一个对象锁。如果定义成静态可以用同一个锁(类锁)

说明synchronized的正确使用和使用范围

* 1、修饰普通方法

* 2、修饰静态方法

* 3、修饰代码块

线程终端机制 stop(),interrupted(),isInterrupted()

stop() 会终止掉"其他线程",导致主线程下的未完成线程没有被执行

interrupted() 线程打中断标记

wait:暂停一个线程执行,有机会被唤醒

notify:唤醒一个暂停的线程,需要竞争CPU资源

notifyAll:唤醒所有被暂停的线程


Future


Executors


ReentrantLock


Condition


Semaphore


ReadWriteLock


StampedLock


CountDownLatch


CyclicBarrier


Phaser


Blinking Phaser


AtomicInteger


BlockingQueue


TransferQueue


Completion Service


ConcurrentHashMap


Fork/Join


Actor模型

并发,我们常常需要关心的是分布式锁的控制

你可能感兴趣的:(Java线程的使用技巧)