做网站怎样实现网上支付,dedecms 英文网站,关于网站建设实训报告,wordpress博客调节字体大小JAVA多线程 并发编程上下文切换如何减少上下文切换减少上下文切换实战 死锁资源限制的挑战什么是资源限制资源限制引发的问题如何解决资源限制的问题在资源限制情况下进行并发编程 并发编程 有的并发程序写得不严谨#xff0c;在并发下如果出现问题#xff0c;定位起来会比较… JAVA多线程 并发编程上下文切换如何减少上下文切换减少上下文切换实战 死锁资源限制的挑战什么是资源限制资源限制引发的问题如何解决资源限制的问题在资源限制情况下进行并发编程 并发编程 有的并发程序写得不严谨在并发下如果出现问题定位起来会比较耗时和棘手。 所以对于Java开发工程师而言笔者强烈建议多使用JDK并发包提供的并发容器和工具类来解决并发问题因为这些类都已经通过了充分的测试和优化。 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最 大限度地并发执行。 并发编程涉及到的为问题 上下文切换问题死锁问题受限于硬件和软件的资源问题等等。 上下文切换 单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现。 CPU通过时间片分配算法来循环执行任务当前任务执行一个时间片后会切换到下一个 任务。但是在切换前会保存上一个任务的状态以便下次切换回这个任务时可以再加载这 个任务的状态。 所以任务从保存到再加载的过程就是一次上下文切换。 使用Lmbench3性能分析工具可以测量上下文切换的时长。 使用vmstat可以测量上下文切换的次数。 如何减少上下文切换 减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。 无锁并发编程。多线程竞争锁时会引起上下文切换所以多线程处理数据时可以用一些办法来避免使用锁如将数据的ID按照Hash算法取模分段不同的线程处理不同段的数据。CAS算法。Java的Atomic包使用CAS算法来更新数据而不需要加锁。使用最少线程。避免创建不需要的线程比如任务很少但是创建了很多线程来处理这样会造成大量线程都处于等待状态。协程在单线程里实现多任务的调度并在单线程里维持多个任务间的切换。 减少上下文切换实战 通过减少线上大量WAITING的线程来减少上下文切换次数. 用jstack命令dump线程信息看看pid为31177的进程里的线程都在做什么。 java/bin/jstack 31177 /home/lingyiwin/dump31177统计所有线程分别处于什么状态发现300多个线程处于WAITINGon object monitor状态 grep java.lang.Thread.State dump31177 | awk {print $2$3$4$5}| sort | uniq -c
39 RUNNABLE
21 TIMED_WAITING(on object monitor)
6 TIMED_WAITING(parking)
51 TIMED_WAITING(sleeping)
305 WAITING(on object monitor)
3 WAITING(parking) 打开dump文件查看处于WAITINGonobjectmonitor的线程在做什么。发现这些线程基本全是JBOSS的工作线程在await。说明JBOSS线程池里线程接收到的任务太少大量线程都闲着。 http-0.0.0.0-7001-97 daemon prio10 tid0x000000004f6a8000 nid0x555e in
Object.wait() [0x0000000052423000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on 0x00000007969b2280 (a org.apache.tomcat.util.net.AprEndpoint$Worker)
at java.lang.Object.wait(Object.java:485)
at org.apache.tomcat.util.net.AprEndpoint$Worker.await(AprEndpoint.java:1464)
- locked 0x00000007969b2280 (a org.apache.tomcat.util.net.AprEndpoint$Worker)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1489)
at java.lang.Thread.run(Thread.java:662)减少JBOSS的工作线程数找到JBOSS的线程池配置信息将maxThreads降到100。 maxThreads250 maxHttpHeaderSize8192
emptySessionPathfalse minSpareThreads40 maxSpareThreads75
maxPostSize512000 protocolHTTP/1.1
enableLookupsfalse redirectPort8443 acceptCount200 bufferSize16384
connectionTimeout15000 disableUploadTimeoutfalse useBodyEncodingForURI true重启JBOSS再dump线程信息然后统计WAITINGonobjectmonitor的线程发现减少了175个。WAITING的线程少了系统上下文切换的次数就会少因为每一次从 WAITTING到RUNNABLE都会进行一次上下文的切换。 grep java.lang.Thread.State dump31177 | awk {print $2$3$4$5}| sort | uniq -c
44 RUNNABLE
22 TIMED_WAITING(onobjectmonitor)
9 TIMED_WAITING(parking)
36 TIMED_WAITING(sleeping)
130 WAITING(onobjectmonitor)
1 WAITING(parking死锁 产生死锁就会造成系统功能不可用。 如下代码演示死锁的场景使线程t1和线程t2互相等待对方释放锁。 package com.thread;public class DeadLockDemo {private static String A A;private static String B B;public static void main(String[] args) {new DeadLockDemo().deadLock();}private void deadLock() {Thread t1 new Thread(new Runnable() {Overridepublic void run() {synchronized (A) {try {Thread.currentThread().sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (B) {System.out.println(1);}}}});Thread t2 new Thread(new Runnable() {Overridepublic void run() {synchronized (B) {synchronized (A) {System.out.println(2);}}}});t1.start();t2.start();}
} 一旦出现死锁业务是可感知的因为不能继续提供服务了那么只能通过dump线程查看到底是哪个线程出现了问题以下线程信息告诉我们是DeadLockDemo类引起的死锁。 Thread-2 prio5 tid7fc0458d1000 nid0x116c1c000 waiting for monitor entry [116c1b000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.ifeve.book.forkjoin.DeadLockDemo$2.run(DeadLockDemo.java:42)
- waiting to lock 7fb2f3ec0 (a java.lang.String)
- locked 7fb2f3ef8 (a java.lang.String)
at java.lang.Thread.run(Thread.java:695)
Thread-1 prio5 tid7fc0430f6800 nid0x116b19000 waiting for monitor entry [116b18000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.ifeve.book.forkjoin.DeadLockDemo$1.run(DeadLockDemo.java:31)
- waiting to lock 7fb2f3ef8 (a java.lang.String)
- locked 7fb2f3ec0 (a java.lang.String)
at java.lang.Thread.run(Thread.java:695)避免死锁的几个常见方法: 避免一个线程同时获取多个锁.避免一个线程在锁内同时占用多个资源尽量保证每个锁只占用一个资源。尝试使用定时锁使用lock.tryLocktimeout来替代使用内部锁机制。对于数据库锁加锁和解锁必须在一个数据库连接里否则会出现解锁失败的情况。 资源限制的挑战
什么是资源限制 资源限制是指在进行并发编程时程序的执行速度受限于计算机硬件资源或软件资源。 如服务器的带宽影响下载硬盘读写速度跟不上CPU执行速度软件资源限制数据库的链接数和socket链接数等。 资源限制引发的问题 并发编程中将代码中串行执行变成并发执行。但因资源受限让在串行执行同时又增加了上下文切换和资源调度的时间综合下来反而并行慢于串行。 如何解决资源限制的问题 对于硬件资源限制 可以考虑使用集群并行执行程序。既然单机的资源有限制那么就使用集群。 比如使用ODPS、Hadoop或者自己搭建服务器集群不同的机器处理不同的数据。可以通过“数据ID%机器数”计算得到一个机器编号然后由对应编号的机器处理这笔数据。 对于软件资源限制可以考虑使用资源池将资源复用。 比如使用连接池将数据库和Socket 连接复用或者在调用对方webservice接口获取数据时只建立一个连接。 在资源限制情况下进行并发编程 根据不同的资源限制调整 程序的并发度比如下载文件程序依赖于两个资源——带宽和硬盘读写速度。 有数据库操作时涉及数据库连接数如果SQL语句执行非常快而线程的数量比数据库连接数大很多则某些线程会被阻塞等待数据库连接。