多线程之一 实现多线程的方式

实现多线程的方式

一、使用Thread实现多线程

定义一个任务,用Runnable来描述。

//打印任务
class PrintRunnable implements Runnable {
    private int num=0;

    public void run() {
        boolean isfinished=false;
        while(!isfinished){
            if(num==200){//i为200时结束
                isfinished=true;
                break;
            }
            System.out.println(num++);
        }
    }
}

调用方式

    public static void main(String[] args){
        Thread thread =new Thread(new PrintRunnable());
        thread.start();
    }

二、使用Executors和Future实现多线程

    public static void main(String[] args){ 
        //产生线程池     
        ExecutorService exec = Executors.newSingleThreadExecutor();     
        //ExecutorService exec = Executors.newCachedThreadPool();       
        //ExecutorService exec = Executors.newFixedThreadPool(5);

        //执行任务
        exec.execute(new PrintRunnable());      
        //关闭
        exec.shutdown();
    }

三、实现带返回结果的多线程

定义带返回结果的任务,用Callable描述。

//并返回结果的打印任务
class PrintCallable implements Callable<Integer>{
    private int num=0;

    @Override
    public Integer call() throws Exception {        
        boolean isfinished=false;
        while(!isfinished){
            if(num==200){//i为200时结束
                isfinished=true;
                break;
            }
            System.out.println(num++);
        }
        //返回结果
        return num;
    }
}

调用方式

    public static void main(String[] args){ 
        //产生线程池     
        ExecutorService exec = Executors.newSingleThreadExecutor();     
        //ExecutorService exec = Executors.newCachedThreadPool();       
        //ExecutorService exec = Executors.newFixedThreadPool(5);

        //执行任务
        exec.execute(new PrintRunnable());      
        //关闭
        exec.shutdown();

        //提交并执行带返回结果的任务
        Future<Integer> future = exec.submit(new PrintCallable());

        try {
            //获取返回结果.get方法会阻塞,直到结果返回
            System.out.println(future.get());
            System.out.println(future.get(5, TimeUnit.MINUTES));//指定超时时间5s
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

几种方式的比较

尽量不直接使用线程,因为线程既充当的工作单元,又是执行机制。而使用Execute则将工作单元和执行机制优雅的分开了。工作单元指的是任务(task),包括Runnable任务和Callable任务。

选择哪种线程池

Executors.newCachedTheadPool:
对于小程序和轻载的服务器,我们可以使用它是个不错的选择
Executors.newFixedThreadPool:
对于大负载的服务器来说,缓存的线程池就不是很好的选择了!在缓存的线程池中,被提交的任务没有排成队,而是直接交给线程执行。如果没有线程可用,则创建新的线程,如若如武器负载较重,以致它所有的cpu都完全被占用,当有更多任务时,则会创建更多的线程,情况则会变得更糟。因此,在大负载的产品服务器中,最好使用Executors.newFixedThreadPool。或者为了最大限度的控制它,可以直接使用ThreadPoolExecutor类。
Executors.newSingleThreadExecutor:
对于在希望在另一个线程中连续运行的事物(长期存活的任务)来说,都是很有用的,例如监听进入的socket连接的任务。对希望在线程中运行的段任务也同样方便。例如,更新本地或远程日志的小任务,或者是事件分发线程。

本文参考了《java编程思想》第4版和《Effective Java中文版》第2版

猜你喜欢

转载自blog.csdn.net/javandroid/article/details/52590186