首页 > 其他分享 >多线程创建方式和常用方法

多线程创建方式和常用方法

时间:2024-07-25 19:56:24浏览次数:17  
标签:常用 执行 run Thread 对象 创建 线程 多线程 public

线程其实是程序中的一条执行路径。怎样的程序才是多线程程序呢?

可以同时有很多人一起进入的网站,而且每一个人互不影响。比如百度网盘,可以同时下载或者上传多个文件。这些程序中其实就有多条执行路径,每一条执行执行路径就是一条线程,所以这样的程序就是多线程程序。

Java提供了几种创建线程的方式

线程创建方式1

Java为开发者提供了一个类叫做Thread,此类的对象用来表示线程。创建线程并执行线程的步骤如下

1.定义一个子类继承Thread类,并重写run方法
2.创建Thread的子类对象
3.调用start方法启动线程(启动线程后,会自动执行run方法中的代码) 

public class MyThread extends Thread{
    // 2、必须重写Thread类的run方法
    @Override
    public void run() {
        // 描述线程的执行任务。
        for (int i = 1; i <= 5; i++) {
            System.out.println("子线程MyThread输出:" + i);
        }
    }
}

 测试类中创建MyThread线程对象,并启动线程

public class ThreadTest1 {
    // main方法是由一条默认的主线程负责执行。
    public static void main(String[] args) {
        // 3、创建MyThread线程类的对象代表一个线程
        Thread t = new MyThread();
        // 4、启动线程(自动执行run方法的)
        t.start(); 

        for (int i = 1; i <= 5; i++) {
            System.out.println("主线程main输出:" + i);
        }
    }
}

 MyThread和main线程在相互抢夺CPU的执行权(注意:哪一个线程先执行,哪一个线程后执行,目前我们是无法控制的,每次输出结果都会不一样

最后我们还需要注意一点:不能直接去调用run方法,如果直接调用run方法就不认为是一条线程启动了,而是把Thread当做一个普通对象,此时run方法中的执行的代码会成为主线程的一部分。此时执行结果是这样的。 

 线程创建方式2

 Java为开发者提供了一个Runnable接口,该接口中只有一个run方法,意思就是通过Runnable接口的实现类对象专门来表示线程要执行的任务。

1.先写一个Runnable接口的实现类,重写run方法(这里面就是线程要执行的代码)
2.再创建一个Runnable实现类的对象
3.创建一个Thread对象,把Runnable实现类的对象传递给Thread
4.调用Thread对象的start()方法启动线程(启动后会自动执行Runnable里面的run方法)

 准备一个Runnable接口的实现类

/**
 * 1、定义一个任务类,实现Runnable接口
 */
public class MyRunnable implements Runnable{
    // 2、重写runnable的run方法
    @Override
    public void run() {
        // 线程要执行的任务。
        for (int i = 1; i <= 5; i++) {
            System.out.println("子线程输出 ===》" + i);
        }
    }
}

再写一个测试类,在测试类中创建线程对象,并执行线程

public class ThreadTest2 {
    public static void main(String[] args) {
        // 3、创建任务对象。
        Runnable target = new MyRunnable();
        // 4、把任务对象交给一个线程对象处理。
        //  public Thread(Runnable target)
        new Thread(target).start();

        for (int i = 1; i <= 5; i++) {
            System.out.println("主线程main输出 ===》" + i);
        }
    }
}

 运行上面代码,结果如下(没有出现下面交替执行的效果,也是正常的)

主线程main输出 ===》1
主线程main输出 ===》2
主线程main输出 ===》3
子线程输出 ===》1
子线程输出 ===》2
子线程输出 ===》3
子线程输出 ===》4
子线程输出 ===》5
主线程main输出 ===》4
主线程main输出 ===》5

 线程创建方式2—匿名内部类

 不想写Runnable实现类,可以直接创建Runnable接口的匿名内部类对象,传递给Thread对象。

public class ThreadTest2_2 {
    public static void main(String[] args) {
        // 1、直接创建Runnable接口的匿名内部类形式(任务对象)
        Runnable target = new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程1输出:" + i);
                }
            }
        };
        new Thread(target).start();

        // 简化形式1:
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程2输出:" + i);
                }
            }
        }).start();

        // 简化形式2:
        new Thread(() -> {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("子线程3输出:" + i);
                }
        }).start();

        for (int i = 1; i <= 5; i++) {
            System.out.println("主线程main输出:" + i);
        }
    }
}

 线程创建方式3

 假设线程执行完毕之后有一些数据需要返回,前面两种方式重写的run方法均没有返回结果。

JDK5提供了Callable接口和FutureTask类来创建线程,它最大的优点就是有返回值。

在Callable接口中有一个call方法,重写call方法就是线程要执行的代码,它是有返回值的

public T call(){
    ...线程执行的代码...
    return 结果;
}

 第三种创建线程的方式:

1.先定义一个Callable接口的实现类,重写call方法
2.创建Callable实现类的对象
3.创建FutureTask类的对象,将Callable对象传递给FutureTask
4.创建Thread对象,将Future对象传递给Thread
5.调用Thread的start()方法启动线程(启动后会自动执行call方法)
   等call()方法执行完之后,会自动将返回值结果封装到FutrueTask对象中
6.调用FutrueTask对的get()方法获取返回结果

先准备一个Callable接口的实现类 

/**
 * 1、让子类继承Thread线程类。
 */
public class MyThread extends Thread{
    // 2、必须重写Thread类的run方法
    @Override
    public void run() {
        // 描述线程的执行任务。
        for (int i = 1; i <= 5; i++) {
            System.out.println("子线程MyThread输出:" + i);
        }
    }
}

再定义一个测试类,在测试类中创建线程并启动线程,还要获取返回结果

public class ThreadTest3 {
    public static void main(String[] args) throws Exception {
        // 3、创建一个Callable的对象
        Callable<String> call = new MyCallable(100);
        // 4、把Callable的对象封装成一个FutureTask对象(任务对象)
        // 未来任务对象的作用?
        // 1、是一个任务对象,实现了Runnable对象.
        // 2、可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果。
        FutureTask<String> f1  = new FutureTask<>(call);
        // 5、把任务对象交给一个Thread对象
        new Thread(f1).start();


        Callable<String> call2 = new MyCallable(200);
        FutureTask<String> f2  = new FutureTask<>(call2);
        new Thread(f2).start();


        // 6、获取线程执行完毕后返回的结果。
        // 注意:如果执行到这儿,假如上面的线程还没有执行完毕
        // 这里的代码会暂停,等待上面线程执行完毕后才会获取结果。
        String rs = f1.get();
        System.out.println(rs);

        String rs2 = f2.get();
        System.out.println(rs2);
    }
}

多线程常用方法

public class MyThread extends Thread{
    public MyThread(String name){
        super(name); //1.执行父类Thread(String name)构造器,为当前线程设置名字了
    }
    @Override
    public void run() {
        //2.currentThread() 哪个线程执行它,它就会得到哪个线程对象。
        Thread t = Thread.currentThread();
        for (int i = 1; i <= 3; i++) {
            //3.getName() 获取线程名称
            System.out.println(t.getName() + "输出:" + i);
        }
    }
}

在测试类中,创建线程对象,并启动线程

public class ThreadTest1 {
    public static void main(String[] args) {
        Thread t1 = new MyThread();
        t1.setName(String name) //设置线程名称;
        t1.start();
        System.out.println(t1.getName());  //Thread-0

        Thread t2 = new MyThread("2号线程");
        // t2.setName("2号线程");
        t2.start();
        System.out.println(t2.getName()); // Thread-1

        // 主线程对象的名字
        // 哪个线程执行它,它就会得到哪个线程对象。
        Thread m = Thread.currentThread();
        m.setName("最牛的线程");
        System.out.println(m.getName()); // main

        for (int i = 1; i <= 5; i++) {
            System.out.println(m.getName() + "线程输出:" + i);
        }
    }
}

效果如下

join方法效果  

public class ThreadTest2 {
    public static void main(String[] args) throws Exception {
        // join方法作用:让当前调用这个方法的线程先执行完。
        Thread t1 = new MyThread("1号线程");
        t1.start();
        t1.join();

        Thread t2 = new MyThread("2号线程");
        t2.start();
        t2.join();

        Thread t3 = new MyThread("3号线程");
        t3.start();
        t3.join();
    }
}

 执行效果是1号线程先执行完,再执行2号线程;2号线程执行完,再执行3号线程;3号线程执行完就结束了。

 

把join()方法去掉,再看执行效果。此时2号线程没有执行完1号线程就执行了(效果是多次运行才出现的,根据个人电脑而异,可能半天也出现不了也是正常的

标签:常用,执行,run,Thread,对象,创建,线程,多线程,public
From: https://blog.csdn.net/Yu2uki/article/details/140654294

相关文章

  • maven 工程pom依赖优化及常用命令
    maven工程pom依赖优化及常用命令1.​​mvndependency:list​​----列出项目的所有jar包登录后复制mvndependency:list-Dverbose1.该命令可以列出项目依赖的所有jar包,-Dverbose参数会把被忽略的jar,即相同jar包的不同版本引入也列出来。输出示例:2.​​mvndependency:......
  • 三维点云中常用的表面重建算法
    表面重建算法起源于计算机视觉和计算几何学领域。早期的研究集中在从二维图像中提取三维信息。然而,随着三维扫描技术的进步,越来越多的研究转向了如何从点云数据中重建表面。三维点云表面重建技术的发展,始于20世纪90年代,主要推动力是激光扫描和结构光扫描的广泛应用。Resulto......
  • 实验15.多线程调度
    简介实验.多线程调度内核线程1.在时钟中断函数中处理中,减少当前线程pcb的tick,tick为0则启动调度2.调度,把当前线程pcb放入就绪队列队尾,把就绪线程队列队首拿出来执行主要代码引导省略内核list.c//文件:list.c//时间:2024-07-25//来自:ccj//描......
  • 一文读懂MySQL数据表索引的类型、创建方法、维护要点
    引言索引是数据库中用于提高查询效率的重要机制。在数据库系统中,索引类似于书籍的目录,它可以帮助数据库系统快速地找到特定数据的位置,从而加快查询速度。通过合理地创建和管理索引,可以显著提升数据库的性能,提高数据检索的效率,降低系统的资源消耗。本文将详细介绍MySQL数据......
  • SPONGE常用教程:蛋白+配体模拟2
    前序课程目录应用场景简述;-[Done]DSDP:蛋白-配体对接;-[Done]XPONGE:蛋白-配体建模,加溶剂;-[Done]SPONGE:能量极小化-NVT-NPT-正式模拟;XPONGE:数据简单后处理。4.SPONGE:能量极小化-NVT-NPT-正式模拟文件下载进入建模文件目录,如下图:SPONGE输入文件采用独特的参......
  • Object类及常用方法
    一、Object类超类、基类,所有类的直接或间接父类,位于继承树的最顶层。任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承。Object类中定义的方法,是所有对象都具备的方法。二、getClass()方法publicfinalClass<?>getClass(){}返回引用中存储的实......
  • Docker常用容器启动命令
    redisdockerrun-p6379:6379--nameredis2-vD:\Docker_Container\redis\conf\redis.conf:/etc/redis/redis.conf-vD:\Docker_Container\redis\data:/data-dredis:7.2.3redis-server/etc/redis/redis.conf--appendonlyyes-p6379:6379:将宿主机的6379端口......
  • Linux常用命令
    目录一、目录指令二、文件指令三、查找类指令find四、打包压缩targzip和bzip2一、目录指令1.1pwd:显示当前目录路径1.2cd:改变所在目录option作用cd/进入根目录cd~切换到用户所在路径下/home/usercd..回到上一级目录cd-返回上次所在的目录......
  • mysql常用语法
    MySQL约束注释--单行注释/*多行注释*/#井号注释MySQL命令执行顺序FROM>ON>JOINWHERE>GROUPBY>HAVING+聚合函数>SELECT>ORDERBY>LIMIT数据库设计——DDLshowdatabases; --查看当前所有的数据库use[数据库名]; --打开指定的数据库showtab......
  • IDEA社区版创建Web项目环境
    问题:IDEA社区版缺少Web项目的插件,可以借助maven创建一个web项目环境。基础环境:IDEA社区版2024.1.4maventomcat1.maven部署配置:不多说,抄作业2.tomcat部署配置:再抄3.IDEA社区版借助maven搭建Web开发环境:还抄主要的问题在于IDEA的版本不一致,在使用maven时,需要附加属性的......