我是靠谱客的博主 勤劳白云,最近开发中收集的这篇文章主要介绍编码的变体,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

到目前为止你所看到的所有简单例子中,线程对象都继承自Thread。这么做很合理,因为
很显然,这些对象仅仅是作为线程而创建的,并不具有其它任何行为。然而,你的类也许
已经继承了其它的类,在这种情况下,就不可能同时继承Thread(Java并不支持多重继
承)。这时,你可以使用“实现Runnable接口”的方法作为替代。要实现Runnable接口,
只需实现run( )方法,Thread也是从Runnable接口实现而来的。


以下例子演示了这种方法的要点:


//: c13:RunnableThread.java
// SimpleThread using the Runnable interface.


publicclass RunnableThreadimplements Runnable {
privateint countDown = 5;
public String toString() {
return"#" + Thread.currentThread().getName() + 
": " + countDown;
  } 
publicvoid run() {
while(true) {
      System.out.println(this);
if(--countDown == 0)return;
    } 
  } 
publicstaticvoid main(String[] args) {
for(int i = 1; i <= 5; i++)
new Thread(new RunnableThread(),"" +
i).start();
// Output is like SimpleThread.java
  } 
}///:~


Runnable 类型的类只需一个 run( )方法,但是如果你想要对这个 Thread 对象做点别
的事情(比如在 toString( )里调用 getName( )),那么你就必须通过调用
Thread.currentThread( )方法明确得到对此线程的引用。这里采用的 Thread 构造器
接受一个 Runnable 对象和一个线程名称作为其参数。
当某个对象具有Runnable接口,即表明它有run( )方法,但也就仅此而已,不像从Thread
继承的那些类,它本身并不带有任何和线程有关的特性。所以要从Runnable对象产生一个
线程,你必须像例子中那样建立一个单独的Thread对象,并把Runnable对象传给专门的
Thread构造器。然后你可以对这个线程对象调用start( ),去执行一些通常的初始化动
作,然后调用run( )。
Runnable接口的方便之处在于所有事物都属于同一个类;也就是说,Runnable允许把基
类和其它接口混在一起。如果你要访问某些资源,只需直接去做,而不用通过别的对象。
不过,内部类也能同样方便地访问外部类的所有部分,所以,成员访问并不是使用Runnalbe
接口形成混和类,而不是“一个Thread子类类型的内部类”的强制因素。


当你使用了Runnable,你通常的意思就是,要用run( )方法中所实现的这段代码创建一
个进程(process),而不是创建一个对象表示该进程。这一点是有争议的,取决于你认
为把线程作为一个对象来表示,或是作为完全不同的一个实体,即进程来表示,这两种方
式哪一种更具实际意义1。如果你觉得应该是一个进程,你就不必拘泥于面向对象的原则,
即“所有事物都是对象”。这也意味着,如果仅仅是想开启一个进程以驱动程序的某个部分,
就没有理由把整个类写成是Runnable类型的。因此,使用内部类把和线程有关的代码隐藏
在类的内部,似乎更合理,如下所示:


//: c13:ThreadVariations.java
// Creating threads with inner classes.
import com.bruceeckel.simpletest.*;


// Using a named inner class:
class InnerThread1 {
privateint countDown = 5;
private Inner inner;
privateclass Innerextends Thread {
    Inner(String name) {
super(name);
      start();
    } 
publicvoid run() {
while(true) {
        System.out.println(this);
if(--countDown == 0)return;
try {
          sleep(10);
        } catch (InterruptedException e) {
thrownew RuntimeException(e);
        } 
      } 
    } 
public String toString() {
return getName() +": " + countDown;
    } 
  } 
public InnerThread1(String name) {
   inner =        newInner(name);
  } 
}
 
// Using an anonymous inner class:
classInnerThread2 {
private      int countDown = 5;
private Thread t;
public InnerThread2(String name) {
    t =    newThread(name) {
public     void run() {
while(true){
         System.out.println(this);
if(--countDown == 0)           return;
try{
           sleep(10);
         } catch(InterruptedException e) {
throw    newRuntimeException(e);
         } 
       } 
      }
public String toString() {
return getName() +          ": " + countDown;
      }
    }; 
   t.start();
  } 
}
 
// Using a named Runnable implementation:
classInnerRunnable1 {
private      int countDown = 5;
private Inner inner;
private          class Inner              implements Runnable {
   Thread t;
   Inner(String name) {
      t= newThread(this,name);
     t.start();
    } 
public     void run() {
while(true){
       System.out.println(this);
if(--countDown == 0)          return;
try{
 
         Thread.sleep(10);
       } catch(InterruptedException e) {
throw    newRuntimeException(e);
       } 
      }
    } 
public String toString() {
return t.getName() +             ":" + countDown;
    } 
  } 
public InnerRunnable1(String name) {
    inner =      newInner(name);
  } 
}
 
// Using an anonymous Runnableimplementation:
classInnerRunnable2 {
private      int countDown = 5;
private Thread t;
public InnerRunnable2(String name) {
    t =    newThread(newRunnable() {
public     void run() {
while(true){
         System.out.println(this);
if(--countDown == 0)           return;
try{
           Thread.sleep(10);
         } catch(InterruptedException e) {
throw    newRuntimeException(e);
         } 
       } 
      }
public String toString() {
return Thread.currentThread().getName() +
": " + countDown;
      }
    },name);
   t.start();
  } 
}
 
// A separate method to run some code as athread:
classThreadMethod {
private      int countDown = 5;


 
 
 
private Thread t;
private String name;
public ThreadMethod(String name) {                this.name =
name; }
public     void runThread() {
if(t ==       null){
      t= newThread(name) {
public     void run() {
while(true){
           System.out.println(this);
if(--countDown == 0)           return;
try{
             sleep(10);
           } catch(InterruptedException e) {
throw    newRuntimeException(e);
           } 
         } 
       } 
public String toString() {
return getName() +           ": " + countDown;
       } 
      };
     t.start();
    } 
  } 
}
 
public     class ThreadVariations {
private      static Test monitor =               new Test();
public     static       void main(String[] args) {
newInnerThread1("InnerThread1");
newInnerThread2("InnerThread2");
newInnerRunnable1("InnerRunnable1");
newInnerRunnable2("InnerRunnable2");
newThreadMethod("ThreadMethod").runThread();
   monitor.expect(new String[] {
"InnerThread1: 5",
"InnerThread2: 5",
"InnerThread2: 4",
"InnerRunnable1: 5",
"InnerThread1: 4",
"InnerRunnable2: 5",
"ThreadMethod: 5",
"InnerRunnable1: 4",
"InnerThread2: 3",
"InnerRunnable2: 4",
"ThreadMethod: 4",
"InnerThread1: 3",
"InnerRunnable1: 3",
"ThreadMethod: 3",
"InnerThread1: 2",
"InnerThread2: 2",
"InnerRunnable2: 3",
"InnerThread2: 1",
"InnerRunnable2: 2",
"InnerRunnable1: 2",
"ThreadMethod: 2",
"InnerThread1: 1",
"InnerRunnable1: 1",
"InnerRunnable2: 1",
"ThreadMethod: 1"
    },Test.IGNORE_ORDER + Test.WAIT);
  } 
}  ///:~
InnerThread1 创建了一个命名的内部类,它继承自 Thread,并且在构造器中创建了一
个此内部类的实例。如果你需要在别的方法中访问此内部类(比如新的方法),这么做就
显得很合理。不过,绝大多数时候创建一个线程的原因仅仅是为了使用 Thread的功能,
所以建立一个命名的内部类往往没有必要。InnerThread2 演示了另一种选择:在构造器
内部建立了一个匿名内部类,它也继承自 Thread,同时它被向上转型为对 Thread的引
用 t。如果该类的别的方法需要访问 t,它们可以通过 Thread的接口访问,并且不需要知
道这个对象的确切类型。
 
例子中的第三、四个类和前两个大致相同,但是它们实现了 Runnable接口而不是从
Thread 继承。这只不过表明了在实现 Runnable接口的情况下,并没有带来更多好处,
而且实际上代码要稍微复杂一些(读起来也是)。所以,除非被迫使用 Runnable,否则
我更倾向于使用Thread。
 
ThreadMethod 类演示了如何在方法内部创建一个线程。当你调用该方法准备运行这个线
程时,在线程启动后该方法返回。当线程只是做一些辅助工作,而不是作为类的基本功能

的时候,这种方案就比在类的构造器中启动一个线程显得更合理。



最后

以上就是勤劳白云为你收集整理的编码的变体的全部内容,希望文章能够帮你解决编码的变体所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部