[多线程] java 实现多线程的几种方式

在java的历史版本中,有两种创建多线程程序的方法

1) 通过创建Thread类的子类来实现(Thread类提供了主线程调用其它线程并行运行的机制)

主要步骤:

自定义类继承Thread类,然后覆盖其中的run方法,使得该线程能够完成特定的工作,使用start方法启动线程,将执行权转交到run.

package com.xwolf.java.thread;

public class ThreadDemo extends Thread {
    
    @Override
    public void run() {
        
        System.out.println("线程的id:"+super.getId()+",线程的名称:"+super.getName()+",线程的优先级:"+super.getPriority());
    }
    
    public static void main(String[] args) {
        
        for (int i=0;i<1;){
            new ThreadDemo().start();
        }
        
    }
}

 

2) 通过实现Runable接口的类来实现(推荐,可以实现数据共享,而且可以避免因为类单继承的局限)

主要步骤:

a>. 创建某个类实现Runnable接口,实现run()方法。

b>. 创建Thread对象,用实现Runnable接口的对象作为参数实例化该Thread对象。

c>. 调用Thread的start方法。

说明:

Thread是一个类,而Runnable是一个接口.

JAVA线程控制着程序执行的主路径;当你用java命令调用JVM时,JVM创建了一个隐式线程来执行main方法.

package com.xwolf.java.thread;

public class RunDemo implements Runnable {

    @Override
    public void run() {
          
        System.out.println("fdsf");
    }
    
    public static void main(String[] args) {
    
        //通过传入一个实现了Runnable接口的对象实例化线程
        Thread thread = new Thread(new RunDemo());
        
        thread.start();
    }

}

3) 在JDK5.0后,使用Executor框架管理线程.

虽然可以使用Thread类来显示的创建线程,但推荐的做法是使用Executor接口,让它来管理Runnable对象的执行.

通常Executor对象会创建并管理一组执行Runnable对象的线程,这组线程被称为线程池,Executor基于生产者-消费者模式.提交任务的执行者是生产者(产生待完成的工作单元),执行任务的线程是消费者(消耗掉这些工作单元)

采用Executor的优势

a) Executor对象能够复用已有的线程,从而消除了为每个任务创建新线程的开销,

b) 它能通过优化线程的数量,提高程序性能,保证处理器一直处于忙碌状,而不必创建过多的线程使程序资源耗尽。

Executor接口的定义[JDK源码引入]

public interface Executor{
    void execute(Runnable command);
}

ExecutorService接口[JDK源码引入]

复制代码
public interface ExecutorService extends Executor {
    void shutdown();
    List<Runnable> shutdownNow();
    boolean isShutdown();
    boolean isTerminated();
    boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException;
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
        throws InterruptedException;
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException;

    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}
复制代码

ExecutorService暗示了生命周期的3种状态:运行(running)、关闭(shutting down)和终止(terminated).
ExecutorService最初创建后的初始状态是运行状态.shutdown方法会启动一个平缓的关闭过程:停止接受新的任务,同时等待已经提交的任务完成-包括尚未开始执行的任务. shutdownNow方法会启动一个强制关闭过程,尝试取消所有运行中的任务和排在队列中尚未开始的任务.在关闭后提交到ExecutorService的任务会抛出RejectedExecution异常.

Executors类,该类是一个独立类,提供一系列灵活的线程池实现和一些有用的预设配置.[JDK源码引入]

复制代码
public class Executors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
    }
    ... ...
}
复制代码

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类。
复制代码

 

 

示例:

package com.xwolf.java.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecuteDemo {

    public static void main(String[] args) {
        //使用动态缓存线程池,池中的线程随着任务数量的变化而变化
        ExecutorService service = Executors.newCachedThreadPool();
        
        for (int i=0;i<4;i++){
            
            //匿名内部类创建接口
            service.execute(new Runnable() {
                
                @Override
                public void run() {
                    
                    for (int j=0;j<6;j++){
                        
                        try {
                            Thread.sleep(3000);
                            
                            System.out.println("线程的名称:"+Thread.currentThread().getName()+" ,线程的id为:"+Thread.currentThread().getId()+" ..Runnable is running ....");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    
                }
            });
            
        }
        //如果线程中任务执行完毕,没有任务需要执行了,就关闭线程池,如果不关闭,程序就不会结束,而是持续等待新的任务.
        service.shutdown();
        
    }

}

传统的实现方式以及上面的线程实现方式都不可能有返回值.在ExecutorService中定义了系列的submit(xxx)方法,该方法可以返回Future<V>接口,通过调用其V get() throws InterruptedException, ExecutionException;就可以获取到线程执行结果.submit可以传滴一个Runnable接口的实现类,也可以传递一个Callable接口的实现类.
Callable接口的实现类[JDK源码引入]

public interface Callable<V> {
    V call() throws Exception;
}

说明:Future<V>代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则get()会使当前线程阻塞,直到计算完成.


编写5.0新线程的步骤

1.先写一个Callable的子类,然后实现call()方法.

2.调用Executors.newXXThreadPool()返回ExecutorService类型.

3.调用ExecutorService中的submit(Callable的子类)方法启动线程.

4.只有调用ExecutorService的shutdown()方法才能真正的离开虚拟机.

package com.xwolf.java.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
 * 通过实现Callable接口来实现多线程
 * @author Administrator
 *
 */
public class CallableDemo implements Callable<Object> {

    @Override
    public Object call() throws Exception {
        for (int i=0;i<5;i++){
            Thread.sleep(3000);
            String str = "线程的名称:"+Thread.currentThread().getName();
            System.out.println(str);
        }
        return null;
    }
    
    public static void main(String[] args) {
        //创建缓存线程池
        ExecutorService service =Executors.newCachedThreadPool();
        
         //指定线程,获取线程返回结果
        Future<Object> future = service.submit(new CallableDemo());
        
        try {
            //从线程中获取结果
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally{
            service.shutdown();
        }
    }

}

该接口扩展了Executor接口,并声明了许多方法用于管理Executor的声明周期。

 

转自:http://www.cnblogs.com/dennisit/p/3690378.html

http://blog.csdn.net/aboy123/article/details/38307539

 

posted @ 2015-03-22 17:46  snow__wolf  阅读(244)  评论(0)    收藏  举报