Java调试教程--多线程调试

2016-02-19 14:57 8 1 收藏

下面是个简单易学的Java调试教程--多线程调试教程,图老师小编详细图解介绍包你轻松学会,喜欢的朋友赶紧get起来吧!

【 tulaoshi.com - 编程语言 】

  摘要

  最有价值的调试工具是以线程为中心的。大部分 Java 错误都与线程交互有关。多线程调试让开发人员可以查看应用程序中运行的每个线程中的执行情况。

  SUN Laura Bennett

  多线程调试基础

  最有价值的调试工具是以线程为中心的。大部分 Java 错误都与线程交互有关。多线程调试让开发人员可以查看应用程序中运行的每个线程中的执行情况。

  由于执行顺序的易变性,查找多线程应用程序中的错误比非线程化情况要困难得多。如果可以按相同的可预料顺序执行指令,那么调试这些应用程序就可以变得非常简单。当然,这将违背多线程化的目标。结果,许多 IDE 调试器在这种情况下都不能起什么作用,因为单步调试代码会减缓调试过程,并禁止重新创建错误事件。

  多线程错误的类型

  这里有几种常见的多线程编码问题需要密切关注:

  访问违规。当两个或更多线程试图访问同一个内存位置时,会发生这种问题。

  死锁。譬如说 Thread1 锁定了 ResourceA,而 Thread2 锁定了 ResourceB。然后Thread1试图锁定 ResourceB,并等待 ResourceB 变成可用的。同时,Thread2试图锁定 ResourceA 并等待 ResourceA 变成可用的。 结果:死锁。防止死锁的一种方法是不要让进程在设置了锁定时睡眠。还可以使用 synchronization() 来确保关键部分的代码一次只能由一个线程访问。

  数据争用错误。数据争用条件会锁定应用程序,这种情况会时常发生,譬如双击鼠标左键。在数据争用的情况下数据通常会遭到破坏。要防止这种错误,应使变量不能被多个线程访问。现在已经有工具可以分析这种问题并标志可能发生数据争用错误的变量。

  同步错误。进行无用信息收集时可能会发生这种问题。Java 会自动处理无用信息收集。此时,所有线程都会从运行状态变成暂挂。

  使用 synchronized() 方法

  不同版本的 JVM 实现线程优先级的方法也可能不同,这会影响线程同步。我们建议您在多个操作系统上测试线程化代码,以验证它是否真正是跨平台的。

  synchronized() 方法创建了一个模拟锁定的代码块。这个用同步方法描绘的代码只允许每次只有一个进程运行它。但不要使用太多的 synchronized 调用,因为它们会直接影响代码性能。实际上,同步停止了多线程化。

  以下显示了使用同步化方法的代码示例。通过重新设置实例变量中表的最大的列大小,这段代码将一个元素添加到表中。可以看到多个线程更新同一个变量值可能会造成破坏。使用同步化方法有助于缓和这个问题。

  

/** Synchronized method to add an element to a table **/
public void addElement( Patient newPatient )
{
synchronized ( lock )
{
Log query = incomingPatient.getLog();
results = query.getAllSearchResults();
for ( int k = 0; k results.length; k++)
{
.... // add to table
setMaxColSize(MyTable);
tableContents.add(MyTable);
}
}
}

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  避免多线程错误

  有一些方法可以避免可怕的线程错误:

  如果依靠线程优先级来使线程保持同步,那么测试 JVM 的各种类就显得非常重要。小心可能发生两个线程同时赋值给 long 和 double 变量。其讨厌的结果是一个线程的更改可能更改某个变量,而第二个线程可能再次改变同一个变量。请考虑对那些变量类型进行同步赋值。

  永不使用 stop() 方法。实际上,Java 2 中反对该方法。它会立即停止进程,但又不进行整理,这会导致许多问题,包括死锁和内存锁定。 应始终通过从 run() 方法返回来终止线程。

  不要重新启动已停止的线程。run() 方法没有被调用,而 isAlive() 方法报告错误,指出实际上线程已死。

  不要独占 CPU。如果程序的一部分独占了 CPU,就应该运行 yield() 方法,此方法可以让其它线程也有机会运行。请参阅这个小示例:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  

double answer = 0;
for (int i=0; i10000; i++) {
for (int j = 0; i10000; j++) {
answer = ((answer * i) + j) / j;
}
Thread.yield(); // Now other threads may run while this
//runs in the background
}

来源:http://www.tulaoshi.com/n/20160219/1608412.html

延伸阅读
标签: Java JAVA基础
使用 Java 编程语言实现线程 Java编程语言使多线程如此简单有效,以致于某些程序员说它实际上是自然的。尽管在 Java 中使用线程比在其他语言中要容易得多,仍然有恍└拍钚枰莆铡R亲〉囊患匾氖虑槭?main() 函数也是一个线程,并可用来做有用的工作。程序员只有在需要多个线程时才需要创建新的线程。 Thre...
1.创建线程   在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。Thread构造函数: public Thread( );  public Thread(Runnable target);  public Thread(String name);&n...
Java5增加了新的类库并发集java.util.concurrent,该类库为并发程序提供了丰富的API多线程编程在Java 5中更加容易,灵活。本文通过一个网络服务器模型,来实践Java5的多线程编程,该模型中使用了Java5中的线程池,阻塞队列,可重入锁等,还实践了Callable, Future等接口,并使用了Java 5的另外一个新特性泛型。 简介 本文将实现...
一、进程与应用程序的区别 进程(Process)是最初定义在Unix等多用户、多任务操作系统环境下用于表示应用程序在内存环境中基本执行单元的概念。以Unix操作系统为例,进程是Unix操作系统环境中的基本成分、是系统资源分配的基本单位。Unix操作系统中完成的几乎所有用户管理和资源分配等工作都是通过操作系统对应用程序进程的控制来实现...

经验教程

146

收藏

29
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部