线程实现的几种方式

发布于:2024-09-18 ⋅ 阅读:(130) ⋅ 点赞:(0)

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


网站公告

今日签到

点亮在社区的每一天
去签到