当前位置: 首页 > article >正文

线程实现的几种方式

1、继承Thread类

import java.util.*;

public class Test {

    /**
     * 打字员线程,每秒打出多少字
     */
    class Typist extends Thread {
        @Override
        public void run() {
            int wordNum = new Random().nextInt(5);
            for(int i=1;i<=5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.getName() + "在第" + i + "秒打了" + wordNum + "个字");
            }
        }
    }

    public void printStart() {
        Thread typist1 = new Typist();
        typist1.setName("打字员A");
        Thread typist2 = new Typist();
        typist2.setName("打字员B");
        Thread typist3 = new Typist();
        typist3.setName("打字员C");
        typist1.start();
        typist2.start();
        typist3.start();
    }

    public static void main(String[] args) {
        /**
         * 主线程结束
         * 打字员A在第1秒打了4个字
         * 打字员B在第1秒打了2个字
         * 打字员C在第1秒打了4个字
         * 打字员C在第2秒打了4个字
         * 打字员B在第2秒打了2个字
         * 打字员A在第2秒打了4个字
         * 打字员A在第3秒打了4个字
         * 打字员C在第3秒打了4个字
         * 打字员B在第3秒打了2个字
         * 打字员A在第4秒打了4个字
         * 打字员B在第4秒打了2个字
         * 打字员C在第4秒打了4个字
         * 打字员B在第5秒打了2个字
         * 打字员C在第5秒打了4个字
         * 打字员A在第5秒打了4个字
         */
        new Test().printStart();
        System.out.println("主线程结束");
    }
}

2、实现Runnable接口(推荐方式)

import java.util.*;

public class Test {

    /**
     * 打字员线程,每秒打出多少字
     */
    class Typist implements Runnable {
        @Override
        public void run() {
            int wordNum = new Random().nextInt(5);
            for(int i=1;i<=5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "在第" + i + "秒打了" + wordNum + "个字");
            }
        }
    }

    public void printStart() {
        Typist typist1 = new Typist();
        Thread t1 = new Thread(typist1);
        Typist typist2 = new Typist();
        Thread t2 = new Thread(typist2);
        Typist typist3 = new Typist();
        Thread t3 = new Thread(typist3);
        t1.setName("打字员A");t2.setName("打字员B");t3.setName("打字员C");
        t1.start();t2.start();t3.start();
    }

    public static void main(String[] args) {
        new Test().printStart();
        System.out.println("主线程结束");
    }
}

3、实现Callable接口,可以从线程中获取返回值


import lombok.Data;

import java.util.*;
import java.util.concurrent.*;

public class Test {

    /**
     * 打字员线程,每秒打出多少字
     */
    @Data
    class Typist implements Callable<Integer> {
        private String name;
        @Override
        public Integer call() throws Exception {
            int wordCount = 0;
            int wordNum = new Random().nextInt(5);
            for(int i=1;i<=5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                wordCount += wordNum;
                System.out.println(this.getName() + "在第" + i + "秒打了" + wordNum + "个字");
            }
            return wordCount;
        }
    }

    public void printStart() throws ExecutionException, InterruptedException {

        Typist t1 = new Typist();
        t1.setName("打字员A");
        FutureTask<Integer> futureTask1 = new FutureTask<>(t1);
        Thread thread1 = new Thread(futureTask1);
        thread1.start();

        Typist t2= new Typist();
        t2.setName("打字员B");
        FutureTask<Integer> futureTask2 = new FutureTask<>(t2);
        Thread thread2 = new Thread(futureTask2);
        thread2.start();

        System.out.println(t1.getName() + "一共打了" + futureTask1.get() + "个字");//get()方法阻塞
        System.out.println(t2.getName() + "一共打了" + futureTask2.get() + "个字");
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Test().printStart();
        System.out.println("主线程任务结束");
    }
}

FutureTask.get()方法阻塞,程序的运行后,最后打印【主线程任务结束】

4、Callable接口+线程池(推荐方式,可以从线程中获取返回值)


import lombok.Data;

import java.util.*;
import java.util.concurrent.*;

public class Test {

    /**
     * 打字员线程,每秒打出多少字
     */
    @Data
    class Typist implements Callable<Integer> {
        private String name;
        @Override
        public Integer call() throws Exception {
            int wordCount = 0;
            int wordNum = new Random().nextInt(5);
            for(int i=1;i<=5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                wordCount += wordNum;
                System.out.println(this.getName() + "在第" + i + "秒打了" + wordNum + "个字");
            }
            return wordCount;
        }
    }

    public void printStart() throws ExecutionException, InterruptedException {
        //固定大小线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        Typist t1 = new Typist();
        t1.setName("打字员A");
        Typist t2 = new Typist();
        t2.setName("打字员B");
        Typist t3 = new Typist();
        t3.setName("打字员C");
        Future<Integer> f1 = executorService.submit(t1);//非阻塞
        Future<Integer> f2 = executorService.submit(t2);
        Future<Integer> f3 = executorService.submit(t3);
        executorService.shutdown();
        System.out.println(t1.getName() + "一共打了" + f1.get() + "个字") ;//阻塞
        System.out.println(t2.getName() + "一共打了" + f2.get() + "个字") ;
        System.out.println(t3.getName() + "一共打了" + f3.get() + "个字") ;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        new Test().printStart();
        System.out.println("主线程任务结束");
    }
}

Future.get()方法阻塞等待t1线程结束,获取线程执行完成后的返回值

应用场景:这种方式适合大数据量计算时,开启多个线程分别执行部分数据,最后通过get()方法的返回值再合并各个线程计算结果,经典的map-reduce


http://www.kler.cn/a/297363.html

相关文章:

  • uniapp 懒加载、预加载、缓存机制深度解析
  • 在内部解决方案与外包RevOps解决方案提供商之间做出选择
  • 全网最适合入门的面向对象编程教程:46 Python函数方法与接口-函数与事件驱动框架
  • Redis 集群:如何实现数据的高效分片与负载均衡
  • shell脚本【一、 特殊变量/子串/特殊扩展变量/父子shell/内置命令、外置命令】
  • 实现一个简单的线程池:C++实战指南
  • 用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)
  • C++为什么要引入智能指针?
  • 2024最新网络安全自学路线,内容涵盖3-5年技能提升
  • 关于OceanBase MySQL 模式中全局索引 global index 的常见问题
  • IIC通信协议笔记
  • 【Kubernetes】常见面试题汇总(二)
  • 欧拉下搭建第三方软件仓库—docker
  • 前端几种常见框架【第一节】
  • 如何理解有效值电流?电流的均方根值
  • 【LabVIEW学习篇 - 20】:人机界面交互设计04
  • 线程的状态(java)
  • 使用WMI改变显示器亮度
  • 浅谈C# MQTT
  • 数据结构之折半查找