Java多线程并发技术

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。

1、 继承Thread类实现多线程

 


public class MyThread extends Thread {

  public void run() { //重写run方法

   System.out.println("MyThread.run()");

  }

}

 

//调用代码

MyThread myThread1 = new MyThread();

MyThread myThread2 = new MyThread();

myThread1.start(); // 启动线程

myThread2.start();


 


Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Thread类的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实现有返回结果的多线程

ExecutorService、Callable、Future这个对象实际上都是属于Executor框架中的功能类。可返回值的任务必须实现Callable接口,类似的,无返回值的任务必须Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现有返回结果的多线程了。

 



  1.      int taskSize = 5;     
  2.    ExecutorService pool = Executors.newFixedThreadPool(taskSize);  // 创建一个线程池  
  3.    // 创建多个有返回值的任务  
  4.    List<Future> list = new ArrayList<Future>();  
  5.    for (int i = 0; i < taskSize; i++) {  
  6.     Callable c = new MyCallable(i + " ");     
  7.     Future f = pool.submit(c);      // 执行任务并获取Future对象  
  8.     list.add(f);  
  9.    }     
  10.   pool.shutdown();    // 关闭线程池   
  11. for (Future f : list) {  
  12.  // 从Future对象上获取任务的返回值,并输出到控制台  
  13.  System.out.println(">>>" + f.get().toString());   //get()是阻塞调用
  14.  }   

  // 实现Callable接口

  1. class MyCallable implements Callable<Object> {  
  2. private String taskNum;    
  3. MyCallable(String taskNum) {  
  4.    this.taskNum = taskNum;  
  5. }    
  6. public Object call() throws Exception {     
  7.    Thread.sleep(1000);   
  8.    return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】";  
  9. }  



    4、 Executors类说明:

    参考文献:http://www.iteye.com/topic/366591

     

    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()方法,会阻塞直到计算完成。

    5、 其他获得线程执行结果的方式:

    javascript:void(0)

    基于FutureTask

    在上述实现中,任务callable被提交后返回一个future用于获得执行结果;

    FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值;

     



    1. public class CallableAndFuture {  
    2.     public static void main(String[] args) {  
    3.         Callable<Integer> callable = new Callable<Integer>() {  
    4.             public Integer call() throws Exception {  
    5.                 return new Random().nextInt(100);  
    6.             }  
    7.         };  
    8.          FutureTask<Integer> future = new FutureTask<Integer>(callable);  
    9.       new Thread(future).start();  
    10.        try {  
    11.           Thread.sleep(5000);// 可能做一些事情  
    12.           System.out.println(future.get());  
    13.      } catch (InterruptedException e) {  
    14.           e.printStackTrace();  
    15.        } catch (ExecutionException e) {  
    16.           e.printStackTrace();  
    17.        }  
    18.    }  

         19.  }  


     


    基于CompletionService的实现方式

     



    1.  public class CallableAndFuture {  
    2.     public static void main(String[] args) {  
    3.      ExecutorService threadPool = Executors.newCachedThreadPool();  
    4.         CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);  
    5.         for(int i = 1; i < 5; i++) {  
    6.             final int taskID = i;  
    7.             cs.submit(new Callable<Integer>() {  
    8.                 public Integer call() throws Exception {  
    9.                     return taskID;  
    10.              }  
    11.            });  
    12.          }  
    13.          // 可能做一些事情  
    14.          for(int i = 1; i < 5; i++) {  
    15.              try {  

            //take 每次获得一个执行完成的future,如果没有就阻塞,与其功能相同的非阻塞调用时poll

    1.                 System.out.println(cs.take().get());  
    2.            } catch (InterruptedException e) {  
    3.                  e.printStackTrace();  
    4.             } catch (ExecutionException e) {  
    5.                 e.printStackTrace();  
    6.              }  
    7.          }  
    8.       }  

           }  


     


    6、 多线程相关函数:

    参考文献:javascript:void(0)

     

    线程中断:javascript:void(0)

    void

    interrupt()  //    中断线程。其实只是设置了中断标志位

    static boolean

    interrupted() //  测试调用该方法的当前线程是否已经中断。同时清除中断标志位

    boolean

    isInterrupted() // 测试this线程是否已经中断。不清除中断标志位

    线程让步

    static void

    yield() //     暂停当前正在执行的线程对象,并执行其他线程

    注意: 如果存在synchronized线程同步的话,线程让步不会释放锁(监视器对象)

    线程休眠:

    static void

    sleep(long millis)//  在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

    注意: 如果存在synchronized线程同步的话,线程休眠不会释放锁(监视器对象),但会释放cpu

     

    线程合并:http://uule.iteye.com/blog/1101994

     void

    join()          等待该线程终止。

     void

    join(long millis)          等待该线程终止的时间最长为 millis 毫秒。

     void

    join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。

    线程合并是优先执行调用该方法的线程,再执行当前线程。内部是用wait方法实现的

     



    1. public class JoinTest {  
    2.     public static void main(String[] args) throws InterruptedException {  
    3.         JoinThread t1 = new JoinThread("t1");  
    4.         JoinThread t2 = new JoinThread("t2");  
    5.         t1.start();   //启动线程
    6.         t2.start();  //启动线程
    7.         t1.join();   //等待该线程执行完毕
    8.         t2.join();  //
    9.         System.out.println("主线程开始执行!");  
    10.    }  

    11. }  

          class JoinThread extends Thread {  

    1.      public JoinThread(String name) {  
    2.        super(name);  
    3.        }  
    4.       public void run() {  
    5.        for(int i = 1; i <= 10; i++)  
    6.             System.out.println(getName() + getId() + "执行了" + i + "次");  
    7.      }  

        } 


     


    7、 线程同步之锁