美文网首页
java创建线程的四种方式

java创建线程的四种方式

作者: 一笑乘风凉 | 来源:发表于2020-08-18 14:12 被阅读0次

    Java使用Thread类代表线程,所有线程都是Thread类或其子类,Java创建线程的方式有4种,它们分别是:
    1、继承Thread类创建线程;
    2、实现Runable接口创建线程(首推);
    3、使用Callable和Future创建线程;
    4、使用线程池,例如Executor框架。

    注意:call()方法有返回值,run()方法没有。

    方式1:Thread

    public class MyThread extends Thread {
    
        public void run(){
            System.out.println("线程");
        }
    }
    
    public class MainTest {
    
        public static void main(String[] args){
            new MyThread().start();
        }
    }
    

    方式2:Runnable

    public class MyThread implements Runnable {
    
        public void run(){
            System.out.println("线程Runnable");
        }
    }
    
    public class MainTest {
    
        public static void main(String[] args){
            MyThread myThread = new MyThread();
            Thread thread = new Thread(myThread);
            thread.start();
        }
    }
    

    或者直接写线程的实现

    public class MainTest {
    
        public static void main(String[] args){
           
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("创建线程方式二");
                }
            }).start();
        }
    }
    

    方式3:Callable或者Future

    public class CallableTest implements Callable<Integer> {
    
        @Override
        public Integer call() throws Exception {
            // 计算1-100的和
            int sum = 0;
    
            for (int i = 1; i <= 100; i++)
                sum += i;
    
            return sum;
        }
    
    }
    
    public class MainTest {
    
        public static void main(String[] args) {
            CallableTest cd = new CallableTest();
            // 使用Callable方式创建线程,需要FutureTask类的支持,用于接收运算结果,可以使用泛型指定返回值的类型
            FutureTask<Integer> result = new FutureTask<>(cd);
            new Thread(result).start();
            int sum = 0;
            // 接收运算结果
            // 只有当该线程执行完毕后才会获取到运算结果,等同于闭锁的效果
            try {
                sum = result.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            System.out.println("sum is " + sum);
        }
    }
    

    方式4:Executor框架

    Executor框架包括:线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等
    ExecutorService的生命周期包括三种状态:运行、关闭、终止。创建后便进入运行状态,当调用了shutdown()方法时,便进入关闭状态,此时意味着ExecutorService不再接受新的任务,但它还在执行已经提交了的任务,当素有已经提交了的任务执行完后,便到达终止状态。

    Executors提供了一系列工厂方法用于创建线程池,返回的线程池都实现了ExecutorService接口
    1、创建固定数目线程的线程池

    public static ExecutorService newFixedThreadPool(int nThreads)
    

    2、创建可缓存的线程池

    public static ExecutorService newCachedThreadPool()
    

    3、创建一个单线程化的Executor

    public static ExecutorService newSingleThreadExecutor()
    

    4、创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
    

    Executor执行Runable任务示例:

    public class MainTest {
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newCachedThreadPool();
    //      ExecutorService executorService = Executors.newFixedThreadPool(5);
    //      ExecutorService executorService = Executors.newSingleThreadExecutor();
                for (int i = 0; i < 5; i++){
                    executorService.execute(new TestRunnable());
                    System.out.println("************* a" + i + " *************");
                }
                executorService.shutdown();
            }
        }
    
        class TestRunnable implements Runnable{
            public void run(){
                System.out.println(Thread.currentThread().getName() + "线程被调用了。");
            }
        }
    
    public class MainTest {
    
        private ExecutorService pool;
    
        @PostConstruct
        public void init(){
            //自定义线程工厂
            pool = new ThreadPoolExecutor(5, 10, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(20),
                    new ThreadFactory() {
                        @Override
                        public Thread newThread(Runnable r) {
                            //线程命名
                            Thread th = new Thread(r,"threadPool"+r.hashCode());
                            return th;
                        }
                    },new ThreadPoolExecutor.CallerRunsPolicy());
    
        }
    
        public void test(){
            pool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "线程被调用了。");
                }
            });
        }
        
    }
    

    Executor实现Callable任务示例:

    public class MainTest {
    
        public static void main(String[] args){
            ExecutorService executorService = Executors.newCachedThreadPool();
            List<Future<String>> resultList = new ArrayList<Future<String>>();
    
            //创建10个任务并执行
            for (int i = 0; i < 10; i++){
                //使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
                Future<String> future = executorService.submit(new TaskWithResult(i));
                //将任务执行结果存储到List中
                resultList.add(future);
            }
    
            //遍历任务的结果
            for (Future<String> fs : resultList){
                try{
                    while(!fs.isDone());//Future返回如果没有完成,则一直循环等待,直到Future返回完成
                    System.out.println(fs.get());     //打印各个线程(任务)执行的结果
                }catch(InterruptedException e){
                    e.printStackTrace();
                }catch(ExecutionException e){
                    e.printStackTrace();
                }finally{
                    //启动一次顺序关闭,执行以前提交的任务,但不接受新任务
                    executorService.shutdown();
                }
            }
        }
        }
    
    class TaskWithResult implements Callable<String>{
        private int id;
    
        public TaskWithResult(int id){
            this.id = id;
        }
    
        /**
         * 任务的具体过程,一旦任务传给ExecutorService的submit方法,
         * 则该方法自动在一个线程上执行
         */
        public String call() throws Exception {
            System.out.println("call()方法被自动调用!!!    " + Thread.currentThread().getName());
            //该返回结果将被Future的get方法得到
            return "call()方法被自动调用,任务返回的结果是:" + id + "    " + Thread.currentThread().getName();
        }
    } 
    

    自定义线程池

    自定义线程池,可以用ThreadPoolExecutor类创建,它有多个构造方法来创建线程池,用该类很容易实现自定义的线程池

    public class MainTest {
    
        public static void main(String[] args){
            //创建等待队列
            BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(20);
            //创建线程池,池中保存的线程数为3,允许的最大线程数为5
            ThreadPoolExecutor pool = new ThreadPoolExecutor(3,5,50,TimeUnit.MILLISECONDS,bqueue);
            //创建七个任务
            Runnable t1 = new MyThread1();
            Runnable t2 = new MyThread1();
            Runnable t3 = new MyThread1();
            Runnable t4 = new MyThread1();
            Runnable t5 = new MyThread1();
            Runnable t6 = new MyThread1();
            Runnable t7 = new MyThread1();
            //每个任务会在一个线程上执行
            pool.execute(t1);
            pool.execute(t2);
            pool.execute(t3);
            pool.execute(t4);
            pool.execute(t5);
            pool.execute(t6);
            pool.execute(t7);
            //关闭线程池
            pool.shutdown();
        }
        }
    
    class MyThread1 implements Runnable{
        @Override
        public void run(){
            System.out.println(Thread.currentThread().getName() + "正在执行。。。");
            try{
                Thread.sleep(100);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:java创建线程的四种方式

          本文链接:https://www.haomeiwen.com/subject/uaphjktx.html