发新帖

JAVA多线程实现的三种方式

zhujun 5月前 47
1、继承Thread类实现多线程
继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的start()实例方法。start()方法是一个native方法,它将启动一个新线程,并执行run()方法。这种方式实现多线程很简单,通过自己的类直接extend  Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法。例如:
public  class  MyThread  extends  Thread  {   
  public  void  run()  {   
    System.out.println("MyThread.run()");   
  }   
}   

在合适的地方启动线程如下:
MyThread  myThread1  =  new  MyThread();   
MyThread  myThread2  =  new  MyThread();   
myThread1.start();   
myThread2.start();   

2、实现Runnable接口方式实现多线程
如果自己的类已经extends另一个类,就无法直接extends  Thread,此时,必须实现一个Runnable接口,如下:
public  class  MyThread  extends  OtherClass  implements  Runnable  {   
  public  void  run()  {   
    System.out.println("MyThread.run()");   
  }   
}   
为了启动MyThread,需要首先实例化一个Thread,并传入自己的MyThread实例:
MyThread  myThread  =  new  MyThread();   
Thread  thread  =  new  Thread(myThread);   
thread.start();   

3、使用ExecutorService、Callable、Future实现有返回结果的多线程
import  java.util.concurrent.*;   
import  java.util.Date;   
import  java.util.List;   
import  java.util.ArrayList;   
   
/** 
*  有返回值的线程 
*/   
@SuppressWarnings("unchecked")   
public  class  Test  {   
public  static  void  main(String[]  args)  throws  ExecutionException,   
        InterruptedException  {   
      System.out.println("----程序开始运行----");   
      Date  date1  =  new  Date();   
   
      int  taskSize  =  5;   
      //  创建一个线程池   
      ExecutorService  pool  =  Executors.newFixedThreadPool(taskSize);   
      //  创建多个有返回值的任务   
      List<Future>  list  =  new  ArrayList<Future>();   
      for  (int  i  =  0;  i  <  taskSize;  i++)  {   
        Callable  c  =  new  MyCallable(i  +  "  ");   
        //  执行任务并获取Future对象   
        Future  f  =  pool.submit(c);   
        //  System.out.println(">>>"  +  f.get().toString());   
        list.add(f);   
      }   
      //  关闭线程池   
      pool.shutdown();   
   
      //  获取所有并发任务的运行结果   
      for  (Future  f  :  list)  {   
        //  从Future对象上获取任务的返回值,并输出到控制台   
        System.out.println(">>>"  +  f.get().toString());   
      }   
   
      Date  date2  =  new  Date();   
      System.out.println("----程序结束运行----,程序运行时间【"   
          +  (date2.getTime()  -  date1.getTime())  +  "毫秒】");   
}   
}   
   
class  MyCallable  implements  Callable<Object>  {   
private  String  taskNum;   
   
MyCallable(String  taskNum)  {   
      this.taskNum  =  taskNum;   
}   
   
public  Object  call()  throws  Exception  {   
      System.out.println(">>>"  +  taskNum  +  "任务启动");   
      Date  dateTmp1  =  new  Date();   
      Thread.sleep(1000);   
      Date  dateTmp2  =  new  Date();   
      long  time  =  dateTmp2.getTime()  -  dateTmp1.getTime();   
      System.out.println(">>>"  +  taskNum  +  "任务终止");   
      return  taskNum  +  "任务返回运行结果,当前任务时间【"  +  time  +  "毫秒】";   
}   
}   

代码说明:
上述代码中Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public  static  ExecutorService  newFixedThreadPool(int  nThreads) 
创建固定数目线程的线程池。
public  static  ExecutorService  newCachedThreadPool() 
创建一个可缓存的线程池,调用execute  将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有  60  秒钟未被使用的线程。
public  static  ExecutorService  newSingleThreadExecutor() 
创建一个单线程化的Executor。
public  static  ScheduledExecutorService  newScheduledThreadPool(int  corePoolSize) 
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。
最新回复 (0)
返回
发新帖
zhujun
主题数
24
帖子数
2
注册排名
1