zoukankan      html  css  js  c++  java
  • Java多线程的四种实现方式

    1.Java多线程实现的方式有四种:
    1.继承Thread类,重写run方法
    2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
    3.通过Callable和FutureTask创建线程
    4.通过线程池创建线程
    2.Thread实现方式
    继承Thread类,重写run()方法,创建Thread对象调用start()方法启动线程。

    public class ThreadDemo extends Thread {
        @Override
        public void run() {
            int t = 1;
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "  " + (t++));
            }
        }
    
        public static void main(String[] args) {
            ThreadDemo td1 = new ThreadDemo();
            ThreadDemo td2 = new ThreadDemo();
            td1.setName("Thread1");
            td2.setName("Thread2");
            td1.start();
            td2.start();
        }
    }

    结果:

    3.Runnable实现方式
    实现Runnable接口,实现run()方法,接口的实现类的实例作为Thread的target传入带参的Thread构造函数,调用start()方法启动线程。

    public class RunnableDemo implements Runnable {
        @Override
        public void run() {
            int t = 1;
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "  " + (t++));
            }
        }
    
        public static void main(String[] args) {
            RunnableDemo rd = new RunnableDemo();
            Thread tr1 = new Thread(rd);
            Thread tr2 = new Thread(rd);
            tr1.setName("Thread1");
            tr2.setName("Thread2");
            tr1.start();
            tr2.start();
        }
    }
    }

    结果:

    3.Callable和FutureTask创建线程实现方式
    (1)创建Callable接口的实现类 ,并实现Call方法;
    (2)创建Callable实现类的实现,使用FutureTask类包装Callable对象,该FutureTask对象封装了Callable对象的Call方法的返回值 ;
    (3)使用FutureTask对象作为Thread对象的target创建并启动线程;
    (4)调用FutureTask对象的get()来获取子线程执行结束的返回值。

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class CallableFutureTaskDemo implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            int t = 1;
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "  " + (t++));
            }
            return t;
        }
    
        public static void main(String[] args) {
            Callable<Integer> cftd1 = new CallableFutureTaskDemo();
            Callable<Integer> cftd2 = new CallableFutureTaskDemo();
            FutureTask<Integer> ft1 = new FutureTask<>(cftd1);
            FutureTask<Integer> ft2 = new FutureTask<>(cftd2);
            Thread t1 = new Thread(ft1);
            Thread t2 = new Thread(ft2);
            t1.setName("Thread1");
            t2.setName("Thread2");
            t1.start();
            t2.start();
            try {
                System.out.println(ft1.get());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    结果:

    5.线程池实现方式

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ExecutorDemo implements Runnable {
        private static int task_num = 2;  //任务数量
    
        @Override
        public void run() {
            int t = 1;
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "  " + (t++));
            }
        }
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            for (int i = 0; i <task_num; i++) {
                ExecutorDemo ed = new ExecutorDemo();
                executorService.execute(ed);
            }
            executorService.shutdown();
        }
    }

    结果:

    java里面的线程池的顶级接口是Executor,Executor并不是一个线程池,而只是一个执行线程的工具,而真正的线程池是ExecutorService。
    java中的有哪些线程池?
    1.newCachedThreadPool创建一个可缓存线程池程
    2.newFixedThreadPool 创建一个定长线程池
    3.newScheduledThreadPool 创建一个定长线程池
    4.newSingleThreadExecutor 创建一个单线程化的线程池
    这里的例子用到的就是newFixedThreadPool 。

    6.总结
    (1)实现Runnable接口比继承Thread类更具有优势!Runnable接口适合多个相同的程序代码的线程去处理同一个资源,可以避免java中的单继承的限制,增加程序的健壮性,而且代码可以被多个线程共享,实现代码和数据独立。

    (2)使用线程池可以减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务,可以根据系统的承受能力,调整线程池中工作线线程的数量。

    (3)实际应用中,可以通过一个boolean标志位来结束线程。

    (4)ExecutorService、Callable都是属于Executor框架。返回结果的线程是在JDK1.5中引入的新特征,还有Future接口也是属于这个框架,有了这种特征得到返回值更方便。
    执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的值(由泛型决定)了。get()方法是阻塞的,即线程无返回结果,get方法会一直等待。此外,ExecutoreService提供了submit()方法,传递一个Callable或Runnable,返回Future。如果Executor后台线程池还没有完成Callable的计算,这调用返回Future对象的get()方法,会阻塞直到计算完成。

  • 相关阅读:
    [TroubleShooting]Neither the partner nor the witness server instance for database is availble
    VM tools安装错误The path "" is not a valid path to the xx generic kernel headers.
    博客导出工具
    puma 配置,启动脚本
    OpenCV改变像素颜色
    Android进程的生命周期
    谷歌地图换接口的新闻
    POJ 3714 Raid 近期对点题解
    CF241B Friends
    2018-2-13-wpf-使用-Dispatcher.Invoke-冻结窗口
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10281572.html
Copyright © 2011-2022 走看看