- 浏览: 3566214 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (1491)
- Hibernate (28)
- spring (37)
- struts2 (19)
- jsp (12)
- servlet (2)
- mysql (24)
- tomcat (3)
- weblogic (1)
- ajax (36)
- jquery (47)
- html (43)
- JS (32)
- ibatis (0)
- DWR (3)
- EXTJS (43)
- Linux (15)
- Maven (3)
- python (8)
- 其他 (8)
- JAVASE (6)
- java javase string (0)
- JAVA 语法 (3)
- juddiv3 (15)
- Mule (1)
- jquery easyui (2)
- mule esb (1)
- java (644)
- log4j (4)
- weka (12)
- android (257)
- web services (4)
- PHP (1)
- 算法 (18)
- 数据结构 算法 (7)
- 数据挖掘 (4)
- 期刊 (6)
- 面试 (5)
- C++ (1)
- 论文 (10)
- 工作 (1)
- 数据结构 (6)
- JAVA配置 (1)
- JAVA垃圾回收 (2)
- SVM (13)
- web st (1)
- jvm (7)
- weka libsvm (1)
- weka屈伟 (1)
- job (2)
- 排序 算法 面试 (3)
- spss (2)
- 搜索引擎 (6)
- java 爬虫 (6)
- 分布式 (1)
- data ming (1)
- eclipse (6)
- 正则表达式 (1)
- 分词器 (2)
- 张孝祥 (1)
- solr (3)
- nutch (1)
- 爬虫 (4)
- lucene (3)
- 狗日的腾讯 (1)
- 我的收藏网址 (13)
- 网络 (1)
- java 数据结构 (22)
- ACM (7)
- jboss (0)
- 大纸 (10)
- maven2 (0)
- elipse (0)
- SVN使用 (2)
- office (1)
- .net (14)
- extjs4 (2)
- zhaopin (0)
- C (2)
- spring mvc (5)
- JPA (9)
- iphone (3)
- css (3)
- 前端框架 (2)
- jui (1)
- dwz (1)
- joomla (1)
- im (1)
- web (2)
- 1 (0)
- 移动UI (1)
- java (1)
- jsoup (1)
- 管理模板 (2)
- javajava (1)
- kali (7)
- 单片机 (1)
- 嵌入式 (1)
- mybatis (2)
- layui (7)
- asp (12)
- asp.net (1)
- sql (1)
- c# (4)
- andorid (1)
- 地价 (1)
- yihuo (1)
- oracle (1)
最新评论
-
endual:
https://blog.csdn.net/chenxbxh2 ...
IE6 bug -
ice86rain:
你好,ES跑起来了吗?我的在tomcat启动时卡在这里Hibe ...
ES架构技术介绍 -
TopLongMan:
...
java public ,protect,friendly,private的方法权限(转) -
贝塔ZQ:
java实现操作word中的表格内容,用插件实现的话,可以试试 ...
java 读取 doc poi读取word中的表格(转) -
ysj570440569:
Maven多模块spring + springMVC + JP ...
Spring+SpringMVC+JPA
这两天为了定位JBOSS老是挂死的问题,学习了一下JAVA多线程方面的知识,在此总结一下
1、在Java程序中,JVM负责线程的调度。线程调度是指按照特定的机制为多个线程分配CPU的使用权。
调度的模式有两种:分时调度和抢占式调度。分时调度是所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间;抢占式调度是根据线程的优先级别来获取CPU的使用权。JVM的线程调度模式采用了抢占式模式。
2、Thread类实际上也是实现了Runnable接口的类。
在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的start()方法来运行多线程代码。
实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是扩展Thread类还是实现Runnable接口来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。
3、JAVA多线程涉及到2个问题,一个是线程的调度,另一个是线程的同步
4、线程的状态有:new、runnable、running、waiting、timed_waiting、blocked、dead
当执行new Thread(Runnable r)后,新创建出来的线程处于new状态,这种线程不可能执行
当执行thread.start()后,线程处于runnable状态,这种情况下只要得到CPU,就可以开始执行了。runnable状态的线程,会接受JVM的调度,进入running状态,但是具体何时会进入这个状态,是随机不可知的
running状态中的线程最为复杂,可能会进入runnable、waiting、timed_waiting、blocked、dead状态:
如果CPU调度给了别的线程,或者执行了Thread.yield()方法,则进入runnable状态,但是也有可能立刻又进入running状态
如果执行了Thread.sleep(long),或者thread.join(long),或者在锁对象上调用object.wait(long)方法,则会进入timed_waiting状态
如果执行了thread.join(),或者在锁对象上调用了object.wait()方法,则会进入waiting状态
如果进入了同步方法或者同步代码块,没有获取锁对象的话,则会进入blocked状态
处于waiting状态中的线程,如果是因为thread.join()方法进入等待的话,在目标thread执行完毕之后,会回到runnable状态;如果是因为object.wait()方法进入等待的话,在锁对象执行object.notify()或者object.notifyAll()之后会回到runnable状态
处于timed_waiting状态中的线程,和waiting状态中的差不多,只不过是设定时间到了,就会回到runnable状态
处于blocked状态中的线程,只有获取了锁之后,才会脱离阻塞状态
当线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,该线程结束
5、当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。
6、设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。可以更改线程的优先级。
JVM从不会改变一个线程的优先级。然而,1-10之间的值是没有保证的。一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。
7、Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。
yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。
结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
8、另一个问题是线程的同步,这个我感觉比调度更加复杂一些
Java中每个对象都有一个“内置锁”,也有一个内置的“线程表”
当程序运行到非静态的synchronized方法上时,会获得与正在执行代码类的当前实例(this实例)有关的锁;当运行到同步代码块时,获得与声明的对象有关的锁
释放锁是指持锁线程退出了synchronized方法或代码块。
当程序运行到synchronized同步方法或代码块时对象锁才起作用。
一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。
9、当提到同步(锁定)时,应该清楚是在哪个对象上同步(锁定)?
10、
obj.wait()
obj.notify()
obj.notifyAll()
关于这3个方法,有一个关键问题是:
必须从同步环境内调用wait()、notify()、notifyAll()方法。只有拥有该对象的锁的线程,才能调用该对象上的wait()、notify()、notifyAll()方法
与每个对象具有锁一样,每个对象也可以有一个线程列表,他们等待来自该对象的通知。线程通过执行对象上的wait()方法获得这个等待列表。从那时候起,它不再执行任何其他指令,直到调用对象的notify()方法为止。如果多个线程在同一个对象上等待,则将只选择一个线程(不保证以何种顺序)继续执行。如果没有线程等待,则不采取任何特殊操作。
11、下面贴几个代码实例,配合jstack命令说明一下
- public class ThreadA {
- public static void main(String[] args) {
- ThreadB b = new ThreadB();// ThreadB status: new
- b.start();// ThreadB status: runnable
- synchronized (b) {
- try {
- System.out.println("等待对象b完成计算。。。");
- Thread.sleep(60000);
- b.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("b对象计算的总和是:" + b.total);
- }
- }
- }
- public class ThreadB extends Thread {
- int total;
- public void run() {
- synchronized (this) {
- for (int i = 0; i < 101; i++) {
- total += i;
- }
- notifyAll();
- }
- }
- }
public class ThreadA { public static void main(String[] args) { ThreadB b = new ThreadB();// ThreadB status: new b.start();// ThreadB status: runnable synchronized (b) { try { System.out.println("等待对象b完成计算。。。"); Thread.sleep(60000); b.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("b对象计算的总和是:" + b.total); } } } public class ThreadB extends Thread { int total; public void run() { synchronized (this) { for (int i = 0; i < 101; i++) { total += i; } notifyAll(); } } }
jstack输出的结果是:
"main" prio=6 tid=0x00846800 nid=0x1638 waiting on condition [0x0092f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.kyfxbl.lock.ThreadA.main(ThreadA.java:20)
- locked <0x22a18a90> (a net.kyfxbl.lock.ThreadB)
"Thread-0" prio=6 tid=0x02bbb800 nid=0x1410 waiting for monitor entry [0x02f0f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at net.kyfxbl.lock.ThreadB.run(ThreadB.java:11)
- waiting to lock <0x22a18a90> (a net.kyfxbl.lock.ThreadB)
可以看到,主线程和新线程在同一个对象上锁定,主线程的方法里执行了Thread.sleep(60000),因此进入了TIMED_WAITING状态,而新线程则进入BLOCKED状态
- public class ThreadA {
- public static void main(String[] args) {
- ThreadB b = new ThreadB();// ThreadB status: new
- b.start();// ThreadB status: runnable
- synchronized (b) {
- try {
- System.out.println("等待对象b完成计算。。。");
- b.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("b对象计算的总和是:" + b.total);
- }
- }
- }
- public class ThreadB extends Thread {
- int total;
- public void run() {
- synchronized (this) {
- try {
- Thread.sleep(60000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- for (int i = 0; i < 101; i++) {
- total += i;
- }
- notifyAll();
- }
- }
- }
public class ThreadA { public static void main(String[] args) { ThreadB b = new ThreadB();// ThreadB status: new b.start();// ThreadB status: runnable synchronized (b) { try { System.out.println("等待对象b完成计算。。。"); b.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("b对象计算的总和是:" + b.total); } } } public class ThreadB extends Thread { int total; public void run() { synchronized (this) { try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } for (int i = 0; i < 101; i++) { total += i; } notifyAll(); } } }
jstack输出的结果是:
"main" prio=6 tid=0x00846800 nid=0x1684 in Object.wait() [0x0092f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x22a18b08> (a net.kyfxbl.lock.ThreadB)
at java.lang.Object.wait(Object.java:485)
at net.kyfxbl.lock.ThreadA.main(ThreadA.java:22)
- locked <0x22a18b08> (a net.kyfxbl.lock.ThreadB)
"Thread-0" prio=6 tid=0x02bcc800 nid=0x19c waiting on condition [0x02f0f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.kyfxbl.lock.ThreadB.run(ThreadB.java:12)
- locked <0x22a18b08> (a net.kyfxbl.lock.ThreadB)
2个线程还是在同一个对象上同步,但这次主线程立刻执行了b.wait()方法,因此释放了对象b上的锁,自己进入了WAITING状态。接下来新线程得到了对象b上的锁,所以没有进入阻塞状态,紧接着执行Thread.sleep(60000)方法,进入了TIMED_WAITING状态
- public class ThreadA {
- public static void main(String[] args) {
- ThreadB b = new ThreadB();// ThreadB status: new
- b.start();// ThreadB status: runnable
- synchronized (b) {
- try {
- System.out.println("等待对象b完成计算。。。");
- b.wait();// ThreadB status: running
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("b对象计算的总和是:" + b.total);
- }
- }
- }
- public class ThreadB extends Thread {
- int total;
- public void run() {
- synchronized (this) {
- for (int i = 0; i < 101; i++) {
- total += i;
- }
- notifyAll();
- try {
- System.out.println("我要睡了");
- Thread.sleep(60000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
public class ThreadA { public static void main(String[] args) { ThreadB b = new ThreadB();// ThreadB status: new b.start();// ThreadB status: runnable synchronized (b) { try { System.out.println("等待对象b完成计算。。。"); b.wait();// ThreadB status: running } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("b对象计算的总和是:" + b.total); } } } public class ThreadB extends Thread { int total; public void run() { synchronized (this) { for (int i = 0; i < 101; i++) { total += i; } notifyAll(); try { System.out.println("我要睡了"); Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
jstack输出的结果是:
"main" prio=6 tid=0x00846800 nid=0x3ec in Object.wait() [0x0092f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x22a18ba0> (a net.kyfxbl.lock.ThreadB)
at java.lang.Object.wait(Object.java:485)
at net.kyfxbl.lock.ThreadA.main(ThreadA.java:20)
- locked <0x22a18ba0> (a net.kyfxbl.lock.ThreadB)
"Thread-0" prio=6 tid=0x02bbb800 nid=0x14b4 waiting on condition [0x02f0f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at net.kyfxbl.lock.ThreadB.run(ThreadB.java:19)
- locked <0x22a18ba0> (a net.kyfxbl.lock.ThreadB)
当主线程执行b.wait()之后,就进入了WAITING状态,但是新线程执行notifyAll()之后,有一个瞬间主线程回到了RUNNABLE状态,但是好景不长,由于这个时候新线程还没有释放锁,所以主线程立刻进入了BLOCKED状态
12、当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程仍然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁被释放
13、与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。
14、在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。
15、JRE判断程序是否执行结束的标准是所有的前台执线程行完毕了,而不管后台线程的状态,因此,在使用后台线程时候一定要注意这个问题。
16、下面说说我们这次JBOSS挂死问题的处理方法
现象:系统运行一段时间之后,发现有几个子系统无法访问了,但是另外几个可以。CPU占用达到100%
观察了一下,发现无法访问的应用都部署在同一个JBOSS里,于是把该JBOSS的堆栈用jstack命令输出
发现里面有大量的线程处于BLOCKED状态,均是在执行到c3p0的一个方法里的某一行时,BLOCKED住了
于是下载c3p0的源码,跟进去看了一下,这是一个同步方法,内部会去获取数据库连接,如果获取到连接,就进行下一步操作,如果获取不到,就执行sleep(long timeout)方法。
反推一下,我猜测可能是这样的:
由于某段代码没有释放数据库连接-->连接池中的连接耗尽-->部分线程无限TIMED_WAITING-->其余线程都BLOCKED-->开启新线程-->频繁引发GC-->占用大量CPU-->应用挂起
后来对所有涉及到数据库连接的代码进行排查,发现确实有几个地方做完数据库操作以后,没有释放连接。把这部分代码改掉,重新启动JBOSS,没有再出现JBOSS挂起的现象
发表评论
-
snmp
2020-04-13 11:07 437https://www.iteye.com/blog/zhan ... -
snmp
2020-04-10 21:33 574https://blog.csdn.net/qq_333141 ... -
服务器监控软件
2019-12-31 11:07 526[ERROR] org.hyperic.sigar.Sigar ... -
多数据源
2019-12-23 22:09 467https://gitee.com/baomidou/dyna ... -
mybatis多数据源
2019-12-23 18:09 461https://blog.csdn.net/qq_288042 ... -
springboot ueditor
2019-12-17 18:26 390https://blog.csdn.net/u01216982 ... -
java支持多数据源
2019-12-13 15:59 467spxcms是否支持多数据源 ... -
java日志
2019-12-10 12:01 309https://blog.csdn.net/peng_wei_ ... -
spring 多数据源
2019-12-06 09:55 439https://www.jb51.net/article/10 ... -
idea
2019-12-04 17:13 418https://blog.csdn.net/dengachao ... -
手机大屏
2019-11-30 16:02 359http://demo.demohuo.top/modals/ ... -
quarz配置
2019-11-08 11:48 481https://blog.csdn.net/BryantLmm ... -
mysql同步
2019-11-06 12:20 359https://blog.csdn.net/baidu_418 ... -
nginx配置多个服务
2019-11-04 20:35 783https://blog.csdn.net/everljs/a ... -
h5 加壳
2019-11-04 16:05 635https://jingyan.baidu.com/artic ... -
jeui 前端框架
2019-10-22 14:30 1217http://www.jemui.com/demo/ http ... -
jeui 维护
2019-10-22 14:29 2http://www.jemui.com/demo/ htt ... -
jeui 维护
2019-10-22 14:29 2http://www.jemui.com/demo/ -
jeui 维护
2019-10-22 14:29 2http://www.jemui.com/demo/ -
jeui 维护
2019-10-22 14:29 2http://www.jemui.com/demo/
相关推荐
Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
### Java多线程学习资料知识点解析 #### 一、引言 Java作为一种广泛使用的编程语言,在并发编程领域具有独特的优势。多线程是Java中实现并发处理的核心技术之一,能够显著提升程序的性能和响应性。本文将深入探讨...
这篇资料深入探讨了Java多线程的相关知识,包括线程的创建、同步与通信、线程的状态管理等。 1. **线程创建** - 继承Thread类:创建一个新类,该类继承自Thread类,并重写run()方法,然后创建该类的实例并调用...
Java多线程读大文件 java多线程写文件:多线程往队列中写入数据
### Java多线程操作数据库:深入解析与应用 在当今高度并发的应用环境中,Java多线程技术被广泛应用于处理数据库操作,以提升系统的响应速度和处理能力。本文将基于一个具体的Java多线程操作数据库的应用程序,深入...
java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题
Java多线程是Java编程语言中一个非常重要的概念,它允许开发者在一个程序中创建多个执行线程并行运行,以提高程序的执行效率和响应速度。在Java中,线程的生命周期包含五个基本状态,分别是新建状态(New)、就绪...
本资料详细讲解了Java多线程的原理,并提供了丰富的实战代码,非常适合Java初学者以及希望深入理解多线程的开发者。 1. **线程的基本概念**:线程是程序执行的最小单位,一个进程中可以有多个线程同时运行。Java...
这份“Java多线程的经典资料.rar”压缩包包含了一份名为“Java线程.pdf”的文档,很可能是关于Java多线程的详细教程或深入解析。 在Java中,多线程主要涉及以下几个关键知识点: 1. **线程创建**:Java提供了多种...
Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,极大地提升了程序的效率和性能。在Java中,实现多线程有两种主要方式:通过实现Runnable接口或者继承Thread类。本案例将深入探讨Java多线程中的关键...
Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...
《汪文君JAVA多线程编程实战》是一本专注于Java多线程编程的实战教程,由知名讲师汪文君倾力打造。这本书旨在帮助Java开发者深入理解和熟练掌握多线程编程技术,提升软件开发的效率和质量。在Java平台中,多线程是...
### Java多线程分页查询知识点详解 #### 一、背景与需求分析 在实际的软件开发过程中,尤其是在处理大量数据时,如何高效地进行数据查询成为了一个关键问题。例如,在一个用户众多的社交平台上,当用户需要查看...
然而,为了更好地管理和控制线程,Java并发包提供了如`ExecutorService`、`Future`、`Callable`等高级接口和类,它们简化了多线程编程,并提供了更好的资源管理。 在处理数据库数据时,我们通常会使用JDBC(Java ...
综上所述,"java多线程查询数据库"是一个涉及多线程技术、线程池管理、并发控制、分页查询等多个方面的复杂问题。通过理解和掌握这些知识点,我们可以有效地提高数据库操作的效率和系统的响应速度。
在Java编程中,多线程并发是...总之,Java的多线程并发实例可以帮助我们更好地理解和实践线程控制、同步机制以及经典的设计模式,提升我们的编程能力。通过不断学习和实践,我们可以编写出高效、安全的多线程并发程序。
### 经典Java多线程资料知识点解析 #### 一、基本原理 1. **进程与线程的概念:** - **进程**:是运行中的应用程序,它包含了一组顺序执行的指令,并且每个进程都有自己的独立内存空间。 - **线程**:是一个并发...
《JAVA多线程教学演示系统》是一篇深入探讨JAVA多线程编程的论文,它针对教育领域中的教学需求,提供了一种生动、直观的演示方式,帮助学生更好地理解和掌握多线程技术。这篇论文的核心内容可能包括以下几个方面: ...
这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点。 首先,多线程的核心概念包括线程的创建与启动。在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。创建后...
在本文中,我们将深入浅出Java多线程编程的世界,探索多线程编程的基本概念、多线程编程的优点、多线程编程的缺点、多线程编程的应用场景、多线程编程的实现方法等内容。 一、多线程编程的基本概念 多线程编程是指...