创建Java多线程的多种方法ouchuquan

前言:编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互。

    概念:

          多进程:面向操作系统的多任务,即一个操作系统运行多个任务。

          多线程:面向程序的多任务,即一个程序运行多个任务。

    创建多线程的方法如下:

    1、通过实现Runnable接口来创建Thread线程:

       其中,Runnable接口(只有一个方法)定义如下:

       

  1. public interface Runnable  
  2. {  
  3.     void run();  
  • }  

 

 

       步骤1:创建实现Runnable接口的类:

       

  1. class SomeRunnable implements Runnable  
  2. {  
  3.     public void run()  
  •     {  
  •       //do something here   
  •     }  
  • }  

 

 

       步骤2:创建一个类对象:

              Runnable oneRunnable = new SomeRunnable();

       步骤3:由Runnable创建一个Thread对象:

              Thread oneThread = new Thread(oneRunnable);

       步骤4:启动线程:

              oneThread.start();

       至此,一个线程就创建完成了。

       注释:线程的执行流程很简单,当执行代码oneThread.start();时,就会执行oneRunnable对象中的void run();方法,

             该方法执行完成后,线程就消亡了。

    2、与方法1类似,通过实现Callable接口来创建Thread线程:

       其中,Callable接口(也只有一个方法)定义如下:

       

  1. public interface Callable<V>  
  2. {  
  3.     V call() throws Exception;  
  • }  

 

步骤1:创建实现Callable接口的类SomeCallable<Integer>(略);

       步骤2:创建一个类对象:

              Callable<Integer> oneCallable = new SomeCallable<Integer>();

       步骤3:由Callable<Integer>创建一个FutureTask<Integer>对象:

              FutureTask<Integer> oneTask = new FutureTask<Integer>(oneCallable);

              注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。

       步骤4:由FutureTask<Integer>创建一个Thread对象:

              Thread oneThread = new Thread(oneTask);

       步骤5:启动线程:

              oneThread.start();

       至此,一个线程就创建完成了。

    3、通过继承Thread类来创建一个线程:

       步骤1:定义一个继承Thread类的子类:

      

  1. class SomeThead extends Thraad  
  2. {  
  3.     public void run()  
  •     {  
  •      //do something here   
  •     }  
  • }  

 

 

       步骤2:构造子类的一个对象:

              SomeThread oneThread = new SomeThread();

       步骤3:启动线程:

              oneThread.start();

       至此,一个线程就创建完成了。

       注释:这种创建线程的方法不够好,主要是因为其涉及运行机制问题,影响程序性能。

    4、通过线程池来创建线程:

       步骤1:创建线程池:

              ExecutorService pool = Executors.newCachedThreadPool();

       步骤2:通过Runnable对象或Callable对象将任务提交给ExecutorService对象:

              Future<Integer> submit(Callable<Integer> task);

              注释:Future是一个接口,它的定义如下:

              

  1. public interface Future<T>  
  2. {  
  3.     V get() throws ...;  
  •     V get(long timeout, TimeUnit unit) throws ...;  
  •     void cancle(boolean mayInterrupt);  
  •     boolean isCancelled();  
  •     boolean isDone();  
  • }  

      至此,一个线程就创建完成了。

      注释:线程池需调用shutdown();方法来关闭线程。

   5、通过事件分配线程直接使用程序中的原有线程:

      使用方法:

      直接调用EventQueue类的静态方法invokeLater():

      EventQueue.invokeLater(oneRunnable);

      注释:调用EventQueue.invokeLater(oneRunnable);会直接执行oneRunnable对象中的run()方法。

 

 

常用

 

前言:编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互。

 

    概念:

 

          多进程:面向操作系统的多任务,即一个操作系统运行多个任务。

 

          多线程:面向程序的多任务,即一个程序运行多个任务。

 

    创建多线程的方法如下:

 

    1、通过实现Runnable接口来创建Thread线程:

 

       其中,Runnable接口(只有一个方法)定义如下:

 

      
[java] view plaincopyprint?
01.public interface Runnable 
02.{ 
03.    void run(); 
04.} 
public interface Runnable
{
    void run();
}

 

       步骤1:创建实现Runnable接口的类:

 

      
[java] view plaincopyprint?
01.class SomeRunnable implements Runnable 
02.{ 
03.    public void run() 
04.    { 
05.      //do something here  
06.    } 
07.} 
class SomeRunnable implements Runnable
{
    public void run()
    {
      //do something here
    }
}

 

       步骤2:创建一个类对象:

 

              Runnable oneRunnable = new SomeRunnable();

 

       步骤3:由Runnable创建一个Thread对象:

 

              Thread oneThread = new Thread(oneRunnable);

 

       步骤4:启动线程:

 

              oneThread.start();

 

       至此,一个线程就创建完成了。

 

       注释:线程的执行流程很简单,当执行代码oneThread.start();时,就会执行oneRunnable对象中的void run();方法,

 

             该方法执行完成后,线程就消亡了。

 

    2、与方法1类似,通过实现Callable接口来创建Thread线程:

 

       其中,Callable接口(也只有一个方法)定义如下:

 

       [java] view plaincopyprint?01.public interface Callable<V>  02.{  03.    V call() throws Exception;  04.}  public interface Callable<V>
{
    V call() throws Exception;
}

 

       步骤1:创建实现Callable接口的类SomeCallable<Integer>(略);

 

       步骤2:创建一个类对象:

 

              Callable<Integer> oneCallable = new SomeCallable<Integer>();

 

       步骤3:由Callable<Integer>创建一个FutureTask<Integer>对象:

 

              FutureTask<Integer> oneTask = new FutureTask<Integer>(oneCallable);

 

              注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。

 

       步骤4:由FutureTask<Integer>创建一个Thread对象:

 

              Thread oneThread = new Thread(oneTask);

 

       步骤5:启动线程:

 

              oneThread.start();

 

       至此,一个线程就创建完成了。

 

    3、通过继承Thread类来创建一个线程:

 

       步骤1:定义一个继承Thread类的子类:

 

      
[java] view plaincopyprint?
01.class SomeThead extends Thraad 
02.{ 
03.    public void run() 
04.    { 
05.     //do something here  
06.    } 
07.} 
class SomeThead extends Thraad
{
    public void run()
    {
     //do something here
    }
}

 

       步骤2:构造子类的一个对象:

 

              SomeThread oneThread = new SomeThread();

 

       步骤3:启动线程:

 

              oneThread.start();

 

       至此,一个线程就创建完成了。

 

       注释:这种创建线程的方法不够好,主要是因为其涉及运行机制问题,影响程序性能。

 

    4、通过线程池来创建线程:

 

       步骤1:创建线程池:

 

              ExecutorService pool = Executors.newCachedThreadPool();

 

       步骤2:通过Runnable对象或Callable对象将任务提交给ExecutorService对象:

 

              Future<Integer> submit(Callable<Integer> task);

 

              注释:Future是一个接口,它的定义如下:

 

             
[java] view plaincopyprint?
01.public interface Future<T> 
02.{ 
03.    V get() throws ...; 
04.    V get(long timeout, TimeUnit unit) throws ...; 
05.    void cancle(boolean mayInterrupt); 
06.    boolean isCancelled(); 
07.    boolean isDone(); 
08.} 
public interface Future<T>
{
    V get() throws ...;
    V get(long timeout, TimeUnit unit) throws ...;
    void cancle(boolean mayInterrupt);
    boolean isCancelled();
    boolean isDone();
}

 

      至此,一个线程就创建完成了。

 

      注释:线程池需调用shutdown();方法来关闭线程。

 

   5、通过事件分配线程直接使用程序中的原有线程:

 

      使用方法:

 

      直接调用EventQueue类的静态方法invokeLater():

 

      EventQueue.invokeLater(oneRunnable);

 

      注释:调用EventQueue.invokeLater(oneRunnable);会直接执行oneRunnable对象中的run()方法。

 

三、两种创建线程方式的比较
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。

采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标(target)对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。


(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。

 

提示:在实际开发中,一般采用实现Runnable接口的方式来创建线程类,因为它具有更好的灵活性和可扩展性。

3)第三种方法是以匿名内部类的方式创建,

内部类也可以,不必匿名.

即可以在一个方法中创建线程,当 方法被调用时,线程即启动,这在编写一些简单线程应用时十分方便,如swing事件中处理 一个可能时间较长的任务,使用这种方法就不致于阻塞用户界面的操作。

public class ThreadTest {
     //程序主方法
      public static void main(String args[]){
            ThreadTest tt =  new ThreadTest();
            for(int i=0;i<10;i++){
                  tt.strartMyThread(i);
             }
      }

      /**
       * 这个方法会启动一个匿名线程线程
       */
      public void strartMyThread(int threadID) {
            //要传入匿名线程内使用的参数必须定义为final型
            final int id=threadID;
            Runnable runner = new Runnable() {
                  public void run(){
                         int i=10;
                        boolean flag=true;
                        while(flag){
                                try{
                            Thread.sleep(3000);
                            //在匿名线程类调用类中的其它方法
                            otherMethod(id);
                               if(i>13){
                                      flag=false;
                             }
                             }catch(Exception ef){}
                       }
                  }
            };
            //最后,启动这个内部线程
            Thread t = new Thread(runner);
            t.start();
      }
      //测试方法
      private void otherMethod(int i){
            System.out.println("可以直接调用类中的其它方法: "+i);
      }
}

在程序中使用匿名内部类创建线程十分方便:在一个方法调用中就可以启动一个线程,而
且这个线程还可以直接调用类中的属性和方法;特别注意的是,在方法中启动匿名内部线程
时,如要向这个线程的 run 方法内传递参数,在创建方法中这个参数必须定义为 final 类型,
如上代码中的

//要传入匿名线程内使用的参数必须定义为final型
            final int id=threadID;

 

posted @ 2012-08-30 18:14  jack_ou  阅读(409)  评论(0编辑  收藏  举报