【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);
		}
	}

}

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.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------------");
		
	}
}

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

在这里插入图片描述

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);
		}
	}
}

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.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);
		}
	}
	
}

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------------");
		
	}
}

运行结果:

在这里插入图片描述

结果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);
		}
	}
	
}

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------------");
		
	}
}

运行结果(其中一种):

在这里插入图片描述

5. 使用多线程的优点

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cpdr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值