java线程栈日志_Java线程堆栈

线程堆栈信息以及解决的问题

1、线程堆栈的信息都包含:

线程的名字,ID,线程的数量等。

线程的运行状态,锁的状态(锁被哪个线程持有,哪个线程再等待锁等)。

调用堆栈(函数的调用层次关系)。调用堆栈包含完整的类名,执行的方法,源代* 码的行数。具体打印出的堆栈信息依赖于你的系统的复杂程度。

2、通过线程堆栈可以解决的问题

无缘无故CPU过高

系统挂起,无响应

系统运行越来越慢(资源争用或者锁竞争)

线程死锁问题

由于线程数量太多导致系统失败(如无法创建线程等)。

如何输出线程堆栈

1、如果获取堆栈日志

JVM虚拟机提供了线程转储的后门,通过后门可以将线程堆栈打印出来,通过这个后门向指定的Java进程发送一个QUIT信号,Java虚拟机收到信号以后就会打印出进程的堆栈信息。一般我们会将日志信息重定向到文件中。

jstack [option] pid >> jstack.info

jstack命令使用如下:

jstack [option] pid

--参数

1. -F 强制打印堆栈

2. -m 打印java 和 native(C++) 堆栈信息

3. -l 打印额外的信息,包括锁信息

要打印堆栈日志,首先要获取java应用的进程号:

命令一:jps

命令二:ps -ef | grep java

解读线程堆栈

1、堆栈日志

下面是某个线程的堆栈日志:

"com.sankuai.sjst.scm.purchase.service.order.OrderReadThriftService-7-thread-3" #214 daemon prio=5 os_prio=0 tid=0x00007fd406b5b000 nid=0x7a4c waiting for monitor entry [0x00007fd30fffc000]

java.lang.Thread.State: BLOCKED (on object monitor)

at java.io.PrintStream.println(PrintStream.java:805)

- waiting to lock <0x00000000c3b916f8> (a java.io.PrintStream)

at org.apache.ibatis.logging.stdout.StdOutImpl.trace(StdOutImpl.java:50)

at org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:145)

at org.apache.ibatis.logging.jdbc.ResultSetLogger.printColumnValues(ResultSetLogger.java:123)

at org.apache.ibatis.logging.jdbc.ResultSetLogger.invoke(ResultSetLogger.java:78)

at com.sun.proxy.$Proxy111.next(Unknown Source)

at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:292)

at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:269)

at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:239)

at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:153)

at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:60)

at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:73)

at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:60)

at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:267)

at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:137)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:96)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:77)

at org.apache.ibatis.session.defa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一段Java代码实现多线程下载: ```java import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class MultiThreadDownload extends Thread { private String url; // 文件下载地址 private String filePath; // 保存路径 private int threadNum; // 线程数量 public MultiThreadDownload(String url, String filePath, int threadNum) { this.url = url; this.filePath = filePath; this.threadNum = threadNum; } @Override public void run() { try { URL downloadUrl = new URL(url); HttpURLConnection httpURLConnection = (HttpURLConnection) downloadUrl.openConnection(); httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); int fileLength = httpURLConnection.getContentLength(); int blockSize = fileLength % threadNum == 0 ? fileLength / threadNum : fileLength / threadNum + 1; RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "rw"); randomAccessFile.setLength(fileLength); randomAccessFile.close(); for (int i = 0; i < threadNum; i++) { int startIndex = i * blockSize; int endIndex = (i + 1) * blockSize - 1; if (endIndex > fileLength) endIndex = fileLength; new DownloadThread(url, filePath, startIndex, endIndex).start(); } } catch (Exception e) { e.printStackTrace(); } } private class DownloadThread extends Thread { private String url; private String filePath; private int startIndex; private int endIndex; public DownloadThread(String url, String filePath, int startIndex, int endIndex) { this.url = url; this.filePath = filePath; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { try { RandomAccessFile randomAccessFile = new RandomAccessFile(filePath, "rw"); randomAccessFile.seek(startIndex); URL downloadUrl = new URL(url); HttpURLConnection httpURLConnection = (HttpURLConnection) downloadUrl.openConnection(); httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); httpURLConnection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); InputStream inputStream = httpURLConnection.getInputStream(); byte[] buffer = new byte[1024]; int length = -1; while ((length = inputStream.read(buffer)) != -1) { randomAccessFile.write(buffer, 0, length); } inputStream.close(); randomAccessFile.close(); } catch (Exception e) { e.printStackTrace(); } } } } ``` 这段代码利用多线程实现文件下载,具体实现过程为:首先获取文件长度,然后根据线程数量计算每个线程需要下载的文件块大小,接着创建多个下载线程,每个下载线程负责下载自己对应的文件块。在下载时,通过设置请求头中的 `Range` 参数实现分块下载,最终将所有分块拼接起来得到完整的文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值