这个程序的不同运行将产生不同的结果这种不确定性来源于两个方面在循环中有一个随机的暂停更为重要的是因为线程执行时间没法保证这是一个关键的原则JVM将根据它自己的时间表运行这些进程(虚拟机一般支持尽可能快地运行这些线程但是没法保证何时运行一个给定线程)对于每个线程可以使一个优先级与之相关联以确保关键线程被JVM处理在次要的线程之前
启动一个线程的第二种方法是使用一个实现Runnable接口的类这个接口也定义在javalang中这个Runnable接口指定一个run()方法然后该方法成为线程的主函数类似于前面的代码
现在Java程序的一般风格是支持继承的接口通过使用接口一个类在后面仍然能够继承(子类化)如果必要的话(例如如果该类要在后面作为一个applet使用的话就会发生这种情况)
三线程的含义
在采用多线程技术增强性能的同时它也增加了程序内部运行的复杂性这种复杂性主要是由线程之间的交互引起的熟悉这些问题是很重要的因为随着越来越多的核心芯片加入到Intel处理器中要使用的线程数目也将相应地增长如果在创建多线程程序时不能很好地理解这些问题那么是调试时将很难发现错误因此让我们先看一下这些问题及其解决办法
等待另一个线程完成假定我们有一个整型数组要进行处理我们可以遍历这个数组每次一个整数并执行相应的操作或更高效地我们可以建立多个线程这样以来让每个线程处理数组的一部分假定我们在开始下一步之前必须等待所有的线程结束为了暂时同步线程之间的活动这些线程使用了join()方法它使得一个线程等待另一个线程的完成加入的线程(线程B)等待被加入的线程(线程A)的完成在join()中的一个可选的超时值使得线程B可以继续处理其它工作如果线程A在给定的时间帧内还没有终止的话这个问题将触及到线程的核心复杂性等待线程的问题下面我们将讨论这个问题
在锁定对象上等待假定我们编写一个航空公司座位分配系统在开发这种大型的程序时为每个连接到该软件的用户分配一个线程是很经常的如一个线程对应一个机票销售员(在很大的系统中情况并非总是如此)如果有两个用户同时想分配同一个座位就会出现问题除非采取特殊的措施否则一个线程将分配该座位而另一个线程将会在做相同的事情两个用户都会认为他们在这趟航班上拥有一个分配的位子
为了避免两个线程同时修改一样的数据项我们让一个线程在修改数据前锁定数据项用这种方法当第二个线程开始作修改时它将等待到第一个线程释放锁为止当这种发生时线程将会看到座位已被分配而对于座位分配的请求就会失败两个线程竞争分配座位的问题也就是着名的竞争条件问题而当竞争发生时有可能导致系统的洩漏为此最好的办法就是锁定任何代码该代码存取一个可由多个线程共同存取的变量
在Java中存在好几种锁选择其中最为常用的是使用同步机制当一个方法的签名包含同步时在任何给定时间只有一个线程能够执行这个方法然后当该方法完成执行时对该方法的锁定即被解除
就是一个方法在这种方法中每次只运行一个线程这种锁机制就打破了上面所描述的竞争条件
使用同步是处理线程间交互的几种方法中的一种JSE 中添加了若干方便的方法来锁定对象大多数这些方法可以在包javautilconcurrentlocks中找到一旦你熟悉了Java线程就应该对它进行详细的研究
在锁机制解决了竞争条件的同时它们也带来了新的复杂性在这种情况下最困难的问题就是死锁假定线程A在等待线程B并且线程B在等待线程A那么这两个线程将永远被锁定这正是术语死锁的意义死锁问题可能很难判定并且必须相当小心以确保在线程之间没有这种依赖性
[] [] [] []