Thread实现了接口Runnable,该接口只有一个run()方法,
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
方法 run 的常规协定是,它可能执行任何所需的动作。
..........................................................................................................
Thread继承了Object和Interface Runnable
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
创建新执行线程有两种方法。
............................................................................................................
一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。
接下来可以分配并启动该子类的实例
............................................................................................................
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
......................................................................
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143);
p.start();
............................................................................
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。
然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。
采用这种风格的同一个例子如下所示:
.............................................................................................
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
......................................................................................................
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
..........................................................................................................
每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。
..........................................................................................................
启动start()方法,必须是Thread的实例。
...........................................................................................................
接口中可以定义方法和常量,但是不能定义变量。
...........................................................................................................
join()等待该线程终止
..............................................................................
用wait()和notify()方法,可以实现线程之间的交互。wait()是该线程的处于等待状态,notify()是唤醒不工作的线程。
在本线程内,可以设置自己的状态为wait(),唤醒别的线程用notify()
其中,notify()和notifyAll()的区别是前者是唤醒在此对象监视器上等待的单个线程,后者是唤醒在此对象监视器上等待的所有线程。
.........................................................................................................
在Java中,线程是抢占式的,不是分时的。
抢占式的调度模型是指可能多个线程是可以运行的,但是只有一个线程得逞。直到该线程不再运行。一个线程不再运行的原因有好多种。
线程的代码可能执行了一个Thread.sleep()调用,要求这个线程暂停一段固定的时间。这个线程可能在等待访问某个资源,而这个资源可访问之前,
这个线程无法继续运行。
.......................................................................
因为Java线程不一定是分时的,所以你必须确保你的代码中的线程会不时的给另外一个
线程运行的机会。这可以通过在各种时间间隔中发出sleep()调用来做到。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
Thread.sleep()和其它使线程暂停一段时间的方法是可以中断的。
线程可以调用另外一个线程的interrupt() 方法, 这将向暂停的线程发出一个
InterruptedException。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
注意Thread类的sleep()方法对当前线程的操作。除非线程因为中断而提早回复执行,否则它不会在这段时间之前回复执行。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
Thread类的另一个方法yield(),可以用来使具有相同优先级的线程获得执行的机会。
如果具有相同优先级的其它线程是可运行的,yield()将把调用线程放到可运行池中
并使另一个线程运行。如果没有相同优先级的线程,yield()什么都不做。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
注意:sleep()调用会给较低优先级线程一个运行的机会。yield()方法只会给相同
优先级线程一个执行的机会。
.......................................................................
有时线程可处于一个未知的状态。isAlive()方法用来确定一个线程是否是活的。
活着的线程并不意味着线程正在运行;对于一个一开始运行但还没有完成任务的线程,
这个方法返回true
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
延迟线程:
sleep()
该方法是使线程停止一段时间的方法。在sleep时间间隔期满后,线程不一定立即恢复执行。
这是因为在那个时刻,其它线程可能正在运行而且,没有被调度为放弃执行,除非:
1、“醒来”的线程具有更高的优先级
2、正在运行的线程因为其它原因而阻塞。
...................................................................
join()
该方法使当前线程停下来等待,直至另一个调用join方法的线程终止。void join (long timeout);
其中 join()方法会挂起当前线程。挂起的时间或者为timeout 毫秒,或者挂起当前线程直
至它所调用的线程终止。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
下面介绍一下用哪种方法生成线程。
第一种:实现Runnable接口
更符合面向对象的设计;单继承;一致性;
第二种方法:扩展Thread
代码更简单。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
实现Runnable的优点:
1、从面向对象的角度来看,Thread类是一个虚拟处理机严格的封装,因此只有当处理机模型修改或扩展时,才可以继承类。
正因为这个原因和区别一个正在运行的线程的处理机、代码和数据部分的意义。
2、由于Java技术只允许单一继承,所以如果你已经继承了Thread,你就不能再继承其它任何类了。
在某些情况下,这会使你只能采用实现Runnable的方法。
3、因为有时你必须实现Runnable,所以你可能喜欢保持一致,并总是使用这种方法。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
继承Thread的优点:
1、当一个run()方法体现在继承Thread类的类中,用this指向实际控制运行的Thread
实例。因此,代码不再需要使用如下控制:
Thread.currentThread().join();
而可以简单地用:
join();
因为代码简单了一些,许多Java编程语言的程序员使用扩展Thread机制。注意:如果你采用这种
方法,在你的代码生命周期的后期,单继承模型可能会给你带来困难。
。。。。。。。。.......................................................
使用Java 技术中的synchronized:
.......................................................................
1、每个对象都有一个标志,它可以被认为是“锁标志”
2、synchronized允许和锁标志交互。即允许独占地存取对象。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
当线程运行到synchronized语句,它检查作为参数传递的对象,并在继续执行之前
试图从对象获得锁标志。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
当线程运行到synchronized语句,它检查作为参数传递的对象,并在继续执行
之前试图从对象获得锁标志。
.....................................................................
释放锁标志:线程执行到synchronized代码块末尾时释放。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
synchronized----放在一起
所有对易碎数据的存取应当同步。
由synchronized保护的易碎数据应当是private的。
正如所暗示的那样,只有当所有对易碎数据的存取位于同步块内,synchronized()
才会发生作用。
所有由synchronized块保护的易碎数据应当标记为private。
考虑来自对象的易碎部分的
数据的可存取性。如果它们不被标记为private,则它们可以由位于类定义之外的代码存取。
这样,你必须确信其他程序员不会省略必需的保护。
一个方法,如果它全部属于与这个实例同步的块,它可以把 synchronized 关键字放到它
的头部。(意思是执行方法的过程当中当前对象被锁定)下面两段代码是等价的:
public void push(char c) {
synchronized(this) {
:
:
}
}
public synchronized void push(char c) {
:
:
}
main方法是主线程。
进程是静态的。
。。。。。。。。。。。。。。。。。。。。。。。。。
在非线程的class中定义的方法,中调用this.wait()方法,意思是停止当前线程。其方法在java.Lang.Object包中。一旦wait过去,对象的锁,不再拥有,而sleep时,还抱着锁。wait过去的,自己不能醒来,必须唤醒。notify()主要是叫醒一个处在wait()状态的线程。
。。。。。。。。。。。。。。。。。。。。。。。。。