• 【java学习—十五】创建多线程的两种方式(2)



    1. 多线程的创建和启动

    Java 语言的 JVM 允许程序运行多个线程,它通过 java.lang.Thread类来实现。
    Thread类的特性
        每个线程都是通过某个特定 Thread 对象的 run() 方法来完成操作的,经常把 run() 方法的主体称为线程体;
        通过该 Thread 对象的 start() 方法来调用这个线程

    run():想要在开启的多线程中运行的代码逻辑,就写到run方法里
    start():用来启动线程,本质上就是开始运行run方法

    2. Thread 类

    构造方法
        Thread():创建新的 Thread 对象
        Thread(String threadname):创建线程并指定线程实例名

        Thread(Runnable target):指定创建线程的目标对象,它实现了 Runnable接口中的 run 方法
        Thread(Runnable target, String name):创建新的 Thread 对象

    3. 创建多线程的两种方式

    3.1.继承Thread类实现多线程

    步骤:
    (1)定义子类继承 Thread 类。
    (2)子类中重写 Thread 类中的 run 方法。
    (3)创建 Thread 子类对象,即创建了线程对象。
    (4)调用线程对象 start 方法:启动线程,调用 run 方法。

    3.1.1. 举例

    子类TestThread继承Thread类

    package day15;
    /**
     * 继承Thread的方式实现多线程
     * @author 14532
     *
     */
    public class TestThread extends Thread{
    	@Override
    	public void run() {
    		System.out.println("多线程运行的代码");
    		for(int i = 0; i <5; i++) {
    			System.out.println("这是多线程的逻辑代码:" + i);
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Test.java

    package day15;
    
    public class Test {
    	public static void main(String[] args) {
    		Thread t0 = new TestThread();
    		
    		t0.start();//启动线程
    		System.out.println("--------------1------------");
    		System.out.println("--------------2------------");
    		System.out.println("--------------3------------");
    		
    		/**
    		 * 多次运行这个main方法之后
    		 * 我们发现main方法中打印的3行与开启线程运行run方法中的打印语句是混合起来的
    		 * 而且main方法中的打印与run方法中打印语句顺序是不固定的
    		 * 为什么?
    		 * 因为main执行t0.start()方法开启多线程之后,就相当于在main方法之外开启一个支流
    		 * 这个时候t0.start()的之后的main方法的其他代码的运行就与run方法运行无关了
    		 * 
    		 * 以当前代码为例
    		 * t0.start()的之后的main方法的其他代码与run方法的代码并行运行
    		 * 就像两条河流一样,各走各的
    		 * 那么控制台输出的结果就是两条并行程序运行的结果的总和,这个结果需要拆成两部分看
    		 * 就可以看到,各自保持自己的输出顺序
    		 * 这个就是多线程的异步,这个异步相对于执行t0.start()主程序来说的
    		 * 简单来说就是开启了线程之后run方法中运行的代码和主程序中t0.start()之后的程序是并行执行的,没有先后关系
    		 */
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    运行结果:(注意每次运行的结果未必相同)

    结果1:
    在这里插入图片描述

    结果2:

    在这里插入图片描述

    3.1.2. 举例2

    注意:Test.java可以开启多个线程,比如再创建 t1、t2 两个线程

    package day15;
    
    public class Test {
    	public static void main(String[] args) {
    		Thread t0 = new TestThread();
    		t0.start();//启动线程
    
    		Thread t1 = new TestThread();
    		t1.start();
    		
    		Thread t2 = new TestThread();
    		t2.start();
    		
    		System.out.println("--------------1------------");
    		System.out.println("--------------2------------");
    		System.out.println("--------------3------------");
    		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果:(其中一种结果)

    在这里插入图片描述

    3.2. 实现Runnable接口

    步骤:

    (1)定义子类,实现 Runnable 接口。
    (2)子类中重写 Runnable 接口中的 run 方法。
    (3)通过 Thread 类含参构造器创建线程对象。
    (4)将 Runnable 接口的子类对象作为实际参数传递给Thread 类的构造方法中。
    (5)调用 Thread 类的 start 方法:开启线程,调用Runnable 子类接口的 run 方法。

    3.2.1. 举例1

    new Thread(new TestRunnable());

    子类实现 Runnable 接口,重写 Runnable 接口中的 run 方法

    package day15;
    /**
     * 通过实现Runnable接口方式实现多线程
     * @author 14532
     *
     */
    public class TestRunnable implements Runnable{
    	@Override
    	public void run() {
    		System.out.println("Runable多线程运行的代码");
    		for(int i = 0; i <5; i++) {
    			System.out.println("这是Runable多线程的逻辑代码:" + i);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Test.java

    package day15;
    
    public class Test {
    	public static void main(String[] args) {
    				
    		Thread t3 = new Thread(new TestRunnable());
    		t3.start();				
    		
    		System.out.println("--------------1------------");
    		System.out.println("--------------2------------");
    		System.out.println("--------------3------------");
    		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行结果:(注意每次运行的结果未必相同)
    结果1:
    在这里插入图片描述

    结果2:

    在这里插入图片描述

    3.2.2. 举例2

    Thread t4 = new Thread(new TestRunnable(), "t-1");

    子类实现 Runnable 接口,重写 Runnable 接口中的 run 方法

    package day15;
    /**
     * 通过实现Runnable接口方式实现多线程
     * @author 14532
     *
     */
    public class TestRunnable implements Runnable{
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + ":Runable多线程运行的代码");
    		for(int i = 0; i <5; i++) {
    			System.out.println(Thread.currentThread().getName() + ":这是Runable多线程的逻辑代码:" + i);
    		}
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Test.java

    package day15;
    
    public class Test {
    	public static void main(String[] args) {
    		
    
    		Thread t4 = new Thread(new TestRunnable(), "t-1");
    		t4.start();
    		
    		Thread t5 = new Thread(new TestRunnable(), "t-2");
    		t5.start();
    		
    		System.out.println("--------------1------------");
    		System.out.println("--------------2------------");
    		System.out.println("--------------3------------");
    		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    运行结果:

    在这里插入图片描述

    结果2:

    在这里插入图片描述

    使用new Thread(new TestRunnable(), "t-1")这种方法能后知道运行的是哪一种线程。

    4. 继承方式和实现方式的联系与区别

        
    区别:

    • 继承 Thread: 线程代码存放 Thread 子类 run 方法中。重写 run 方法
    • 实现 Runnable :线程代码存在接口的子类的 run 方法。实现 run 方法

    实现接口方式的好处:

    • 避免了单继承的局限性;
    • 多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。

    注:一般使用实现接口方式来实现多线程

    举例:

    package day15;
    /**
     * 通过实现Runnable接口方式实现多线程
     * @author 14532
     *
     */
    public class TestRunnable implements Runnable{
    	
    	int count = 0;
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + ":Runable多线程运行的代码");
    		for(int i = 0; i <5; i++) {
    			count++;
    			System.out.println(Thread.currentThread().getName() + ":这是Runable多线程的逻辑代码:" + count);
    		}
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Test.java

    package day15;
    
    public class Test {
    	public static void main(String[] args) {
    		
    		
    		Runnable run = new TestRunnable();
    		
    		Thread t4 = new Thread(run, "t-1");
    		t4.start();
    		
    		Thread t5 = new Thread(run, "t-2");
    		t5.start();
    		
    		
    		
    		System.out.println("--------------1------------");
    		System.out.println("--------------2------------");
    		System.out.println("--------------3------------");
    		
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    运行结果(其中一种):

    在这里插入图片描述

    5. 使用多线程的优点

    多线程程序的优点:
        ①提高应用程序的响应。对图形化界面更有意义,可增强用户体验。
        ②提高计算机系统 CPU 的利用率。
        ③改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改。(解释如下)

    如果在一个方法里有1000行代码,前300行、中间300行、后400行这三段代码没有因果关系,这种情况我们就可以使用线程处理,把前中后三段代码分别放在不同线程中去运行,这样三段代码就是并行运行的。

  • 相关阅读:
    北大青鸟昌平校区:自己的想法还需要他人左右吗?
    第一章 绪论
    【C++】C++ 语言对 C 语言的加强 ④ ( C 语言中的三目运算符 - 不能作为左值 | C++ 语言中的三目运算符增强 | C 语言中三目运算符作为左值使用 )
    状态机的技术选型看这篇就够了,最后一个直叫好!!!
    el-table 多表格弹窗嵌套数据显示异常错乱问题
    HarmonyOS 3.1 API9 集成认证服务提示client id or secret error.
    2024年FPGA可以进吗
    Vue:(五)事件初探
    在HBuilderX中配置Vue Router的步骤
    Oracle GoldenGate(OGG)到入土
  • 原文地址:https://blog.csdn.net/weixin_44883789/article/details/134427429