关于如何创建自己的Thread工具类

@筱筱斌 2024-01-22 10:16:59

我正在学习多线程方面知识,在完成了代码编写后我突然想将其作为一个工具类来使用,先上代码

如下是我的代码:

public class ThreadUtilLink {
    public static void main(String[] args) {
        long startTime = new Date().getTime();
        List<Integer> list = new LinkedList<Integer>();
        // 创建数据样本
        for (int i = 0; i < 100000; i++) {
            list.add(i);
        }
        List<CallableTest> threadList = new LinkedList<CallableTest>();
        // 数据划分 将list分为splitListNum份,并返回对应的List<list>
        List<List<Integer>> lists = SplitList.averageAssignByNum(list, 6);

        for (List<Integer> integerList : lists) {
            CallableTest ct = new CallableTest(integerList);
            // 存储线程
            threadList.add(ct);
        }
        // 反转顺序
        Collections.reverse(threadList);
        List<FutureTask<Integer>> taskList = new LinkedList<FutureTask<Integer>>();
        // 遍历线程并执行
        for (CallableTest callableTest : threadList) {
            FutureTask<Integer> ft = new FutureTask<Integer>(callableTest);
            Thread td  = new Thread(ft,(threadList.indexOf(callableTest)+1)+"线程");
            td.start();
            // 回收结果
            taskList.add(ft);
        }
        Collections.reverse(taskList);
        for (FutureTask<Integer> integerFutureTask : taskList) {
            //获取并输出子线程call()方法的返回值
            try {
                System.out.println((taskList.indexOf(integerFutureTask)+1)+"线程共处理数据:" + integerFutureTask.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        long stopTime = new Date().getTime();
        System.out.println("共耗时 " + (stopTime - startTime)+" ms");

    }
}
class CallableTest implements Callable<Integer> {
    public CallableTest() {
    }

    List<Integer> list;
    public CallableTest(List<Integer> list) {
        this.list = list;
    }

    //复写call() 方法,call()方法具有返回值
    public Integer call() throws Exception {
        int i = 0;
        for( ; i<list.size(); i++){

//            System.out.println(Thread.currentThread().getName() + "的变量值为:" + list.get(i));
        }
        return list.size();
    }
}

这是我突发奇想做的一个多线程的代码,跑起来还不错,当然不排除还有问题,因为我发现每次第一个线程的完成结果打印并不在结尾位置:

1线程共处理数据:1667

...

...

2线程共处理数据:1667
3线程共处理数据:1667
4线程共处理数据:1667
5线程共处理数据:1667
6线程共处理数据:1665

不过我也不太清楚有什么影响,但是感觉不对劲。希望大家如果能看出来为什么的话和我说一声嘿嘿。

先回归正题,因上所以我想把它打成jar包那种形式,然后在每次调用ThreadUtilLink这个类的时候可以搞成如下的形式:

ThreadUtilLink th = new ThreadUtilLink(list,5);
    @Override
    public Integer call() throws Exception {
        int i = 0;
        for( ; i<list.size(); i++){

            System.out.println(Thread.currentThread().getName() + "的变量值为:" + list.get(i));
        }
        return list.size();
    }

该如何操作嘞,我觉得这样会方便点,但不知道该如何搞,求帮助!


我自己写了一下,代码如下:

public class ThreadUtilLink<E> {
    private List<E> list = new LinkedList<E>();
    private int num = 5;

    public ThreadUtilLink(List<E> list, int num) {
        this.list = list;
        this.num = num;
    }

    public static void main(String[] args) {
        List<String> list = new LinkedList<String>();
        // 创建数据样本
        for (int i = 0; i < 10000; i++) {
            list.add(String.valueOf(i));
        }

//        ThreadUtilLink<String> link = new ThreadUtilLink<String>(list,5);
        ThreadUtilLink<String> link = new ThreadUtilLink<String>(list, 5);

        link.CreateThread();

    }

    public void CreateThread() {
        long startTime = new Date().getTime();

        List<CallableTest> threadList = new LinkedList<CallableTest>();
        // 数据划分 将list分为splitListNum份,并返回对应的List<list>
        List<List<E>> lists = SplitList.averageAssignByNum(this.list, this.num);

        for (List<E> integerList : lists) {
            CallableTest ct = new CallableTest(integerList);
            // 存储线程
            threadList.add(ct);
        }
        // 反转顺序
        Collections.reverse(threadList);
        List<FutureTask<Integer>> taskList = new LinkedList<FutureTask<Integer>>();
        // 遍历线程并执行
        for (CallableTest callableTest : threadList) {
            FutureTask<Integer> ft = new FutureTask<Integer>(callableTest);
            Thread td = new Thread(ft, (threadList.indexOf(callableTest) + 1) + "线程");
            td.start();
            // 回收结果
            taskList.add(ft);
        }
        Collections.reverse(taskList);
        for (FutureTask<Integer> integerFutureTask : taskList) {
            //获取并输出子线程call()方法的返回值
            try {
                System.out.println((taskList.indexOf(integerFutureTask) + 1) + "线程共处理数据:" + integerFutureTask.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        long stopTime = new Date().getTime();
        System.out.println("共耗时 " + (stopTime - startTime) + " ms");


    }



    class CallableTest implements Callable<E> {
        List<E> list;
        public CallableTest(List<E> list) {
            this.list = list;
        }

        //复写call() 方法,call()方法具有返回值
        public E call() throws Exception {
            int i = 0;
            for (; i < list.size(); i++) {

                System.out.println(Thread.currentThread().getName() + "的变量值为:" + list.get(i));
            }
            return list.size();
        }
    }
}

不过有几个问题:

1、CallableTest这个类的实现类Callable的泛型与call()方法的返回值必须要相同,如果我想个性化call方法的话这里就成了一个阻碍,因为我无法灵活的设定返回值。这部分该如何解决呢?

2、如何把call()方法做成必须重写的方法呢?通过在call方法外单独写个方法然后在call中调用?

...全文
776 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
joedai 01-24
  • 打赏
  • 举报
回复

mark

该课程由付强老师主讲,系统的、全面的、具体的讲解了java入门的知识。可以使初级的学员入门。Java入门Java的历史、Java的版本、Java的优势、软件行业前景Java开发环境搭建、编写Java入门练习虚拟机的运行机制、Java的平台无关性、虚拟机垃圾回收机制基础语法关键字、标识符、Java数据类型分类、基础数据类型、取值范围变量、常量、三种注释、生成doc文档、运算符、表达式if语句、switch语句、嵌套判断for语句、while语句、do-while语句、嵌套循环类和对象面向过程和面向对象的区别类的构成、访问修饰符、对象的内存分配this关键字、按值传递与按引用传递、对象的初始化顺序高级类特性类的继承、父子类的初始化顺序、单继承性方法的覆盖、重载、super关键字、多态、instanceof关键字、强制类型转换、static关键字、final关键字数组和枚举一维数组的应用及内存分配多维数组的应用及内存分配数组的复制、数组的按引用传递排序算法:冒泡、直接选择、插入选择、希尔、快速、归并、堆排序Arrays工具类的应用枚举类型的应用常见类的使用Object类的底层及应用、Objects类String类的底层及应用、正则表达式StringBuffer和StringBuilder的底层及应用Math类的应用、包装类的应用日期类的应用:Date、DateFormat、Calendar、LocalDateTime、Instant、LocalDate、MonthDay、ZonedDateTime、YearMonth、新旧日期转换BigInteger和BingDecimal、DecimalFormatSystem类、Scanner类抽象类和接口抽象类的规则及应用接口的规则及应用默认方法、静态方法、函数式接口、Lambda表达式异常异常的定义异常的处理:抓(try-catch-finally)、抛(throws)异常的分类、自定义异常的应用、throw关键字集合框架集合框架结构:接口、实现类Collection接口的方法、Set接口的方法、List接口的方法、Map接口的方法Array、Linked、Hash、Tree底层实现原理泛型的作用、Collections工具类、历史集合类I/O流Path类的原理及应用、Files类的原理及应用文件字节流FileInputStream的原理及应用对象类、缓冲流、数据流的原理及应用字符流的原理及应用多线程进程与线程的概念、查看线程对象Java内存模型线程的创建与启动:扩展Thread类、实现Runnable接口、实现Callable接口、线程池线程状态的转换:新建、就绪、运行、阻塞、死亡线程的调度:sleep、yield、join、interrupt、wait后台线程、定时任务线程的并发与同步、同步锁、同步块、线程安全的类Lock接口、CAS、volatile修饰符内部类成员内部类、本地内部类的应用匿名内部类的原理及引用、Lambda表达式设计模式基础设计模式概念、框架概念7大设计原则:开闭原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特原则、里氏替换原则、合成复用原则单例模式、工厂模式、模板模式、代理模式、装饰模式、适配器模式、外观模式、策略模式、观察者模式、命令模式、备忘录模式、观察者模式反射反射包Class类的使用反射获取类属性、方法、构造器通过反射创建类对象/通过反射调用方法反射的应用

50,449

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧