【JAVASE】多线程(一)----线程概述以创建

1、多线程概述

        1.1、什么是进程

        1)什么是进程?

                 进程:正在进行的程序,是系统进行资源分配和调用的独立单位。

                                  每一个进程都有它自己的内存空间和系统资源。

        2)多进程有和意义?

                 A:充分使用系统资源

                 B:提高用户体验

       1.2、什么是线程

        1)什么是线程?

                 线程:一个进程中可以执行多条任务,每一个任务,我们可以任务是一条线程

                          是进程中的单个顺序控制流,是一条执行路径

                 程序启动,至少要开启1条线程,执行主程序。如果要启动多个任务,就开启多个线               程,多个线程之间有自己独立的内存空间。独立运行,互不干扰

                一个进程如果只有一条执行路径,则称为单线程程序。

                一个进程如果有多条执行路径,则称为多线程程序。

        2)多线程有何意义?

                 提高了程序的执行效率

        3)线程是不是越多越好呢?

                不是,对于单个CPU而言,CPU同一时刻,只能执行一条线程。为什么我们的程序看起          来是多线程运行呢?因为CPU会在各个线程之间进行快速的切换,快到你无法察觉,切换是           随机的。

                 如果线程过多,那么同一时间段,每个线程被执行的时间变少了。

        4)JVM运行时,是单线程还是多线程

                 JVM运行的时候,至少要启动一条线程,来执行我们的main函数。

                JVM中,有一个东西:垃圾回收器,这个是在后台运行的,这个程序的运行跟我们的                main函数互不干扰。垃圾回收也有自己独立的线程!

         JVM至少有2条线程,main函数线程,和垃圾回收线程。是多线程程序。

         5)main函数单线程运行图解

2、实现多线程

        2.1、方式一:继承Thread

        2.2.1 、Thread类介绍

        Java提供了一个API,专门实现多线程的程序:Thread类

        要启动一个线程,调用系统资源,开辟内存空间。很麻烦。

        创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。

         2.1.2、实现步骤及演示

        1)步骤:

                 A:自定义类,继承Thread,成为线程类

                 B:重写run方法

                 C:创建线程类的对象

                 D:启动线程

        2)代码实现:

/*
 * 演示:实现多线程的方式1:继承Thread
 * 步骤:
 * 	A:自定义类,继承Thread,成为线程类
 * 	B:重写run方法
 * 	C:创建线程类的对象
 * 	D:启动线程
 */
// A:自定义类,继承Thread,成为线程类
class MyThread extends Thread{
	// B:重写run方法
	public void run() {
		// 写任务要执行的代码
		for( int i = 0; i < 100; i++){
			System.out.println(i);
		}
	}
}
public class ThreadDemo {
	public static void main(String[] args) {
		// C:创建线程类的对象
		MyThread mt = new MyThread();
		// D:启动线程
//		mt.run();// 这里直接调用run方法,并没有启动线程。仅仅是调用了对象中的普通方法。没意义
		mt.start();// 首先启动线程,然后会去执行run方法。所以即启动了线程,又执行了run方法
		
		for( int i = 0; i < 100; i++){
			System.out.println("main ... " + i);
		}
	}
}

        2.1.3、几个疑问

        1)为什么要继承Thread类?

         继承了Thread类,我们的类就是线程类,就可以使用线程类中的各种功能。同时也可以重写run方法,写咱们自己要执行的代码

        2)为什么要复写run方法?

         API的设计者,在设计多线程的时候,不知道后面人们会想执行什么任务代码,怎么办? API是这样设计的:当调用start方法启动线程以后,JVM会自动的去调用run方法。

         我们只需要去重写run方法,然后在run写我们自己要执行的任务代码,那么start之后就一定会调用我们重写的run方法。我们的任务代码就一定会被执行到。

        3)为什么要调用start而不是run?

         run方法:仅仅是用来封装线程的任务代码。无法启动线程。

         strart方法:首先调用系统资源,启动一个线程,然后还会去调用我们写好的run方法。这样即启动了线程,又执行了run方法。

面试题:start方法和run方法的区别?

         run:封装线程任务的。

         start:可以启动线程,并且执行run方法。

        4)线程是否可以多次启动?

        正确的启动多个线程方法:

        2.1.4、获取、设置线程名称

        String getName() 返回该线程的名称。

        void setName(String name) 改变线程名称,使之与参数 name 相同。

/*
 * 演示:设置和获取线程的名称
 * 	String getName() 返回该线程的名称 
 * 	void setName(String name) 改变线程名称,使之与参数 name 相同 
 * 分析:
 * 	main函数所在的线程,不是我们创建的,而是虚拟机创建的。这个线程对象是谁,我们根本不知道。
 * 	因此,我们无法调用其getName或者setName功能
 * 
 * 	所以,我们需要获取main函数所在的线程的对象。怎么获取线程对象呢?
 * 		static Thread currentThread() 返回对当前正在执行的线程对象的引用 
 * 注意:
 *  A:线程的默认名称:Thread-x  x是一个从0 开始递增的整数!
 *  B:main函数的所在线程的名称:main
 * 
 */
class MyThread extends Thread{
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(this.getName() + " ... " + i);
		}
	}
}
public class ThreadDemo {
	public static void main(String[] args) {
		// 创建线程对象
		MyThread mt1 = new MyThread();
		MyThread mt2 = new MyThread();
		// 设置线程的名称
		mt1.setName("汤姆");
		mt2.setName("杰瑞");
		// 启动线程
		mt1.start();
		mt2.start();
		
//		Thread t = Thread.currentThread();// 谁执行这行代码,获取的就是谁的线程
		
		for (int i = 0; i < 10; i++) {
			System.out.println(Thread.currentThread().getName() + " ... " +i);
		}
	}
}

         2.1.5、多线程程序运行路径图解

        2.2、方式二:实现Runnable接口

        2.2.1、Runnable接口介绍

         我们发现,这个接口中有一个run方法:

 

        我们发现,Thread类实现了Runnable接口,很明显,Thread中的run就是Runnable中的run方法。

        我们知道run方法是用来封装线程任务的。所以Runnable接口,就是一个用来封装线程任务的接口

        如果一个类,实现了Runnable,并且实现了run方法。这个类我们就称为任务类。

         2.2.2、实现步骤

        创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。

        步骤:

                 A:自定义类,实现Runnable接口,这个类就是任务类

                 B:实现 run 方法

                C:创建任务对象

                D:创建Thread对象,并且把任务对象作为参数传递

                E:启动线程

        Thread类的构造函数:

        Thread(Runnable target) 分配新的 Thread 对象。

        Thread(Runnable target, String name) 分配新的 Thread 对象。

/*
 * 演示:方式2实现多线程:实现Runnable
 * Thread类的构造函数:
 * 	Thread(Runnable target) 分配新的 Thread 对象。 
 * 	Thread(Runnable target, String name) 分配新的 Thread 对象。
 * 步骤:
 * 	A:自定义类,实现Runnable接口,这个类就是任务类
 * 	B:实现 run 方法
 * 	C:创建任务对象
 * 	D:创建Thread对象,并且把任务对象作为参数传递
 * 	E:启动线程
 */
// A:自定义类,实现Runnable接口,这个类就是任务类
class MyTask implements Runnable{
	// B:实现 run 方法
	@Override
	public void run() {
		for( int i = 0; i < 10; i++){
			System.out.println(Thread.currentThread().getName() + " ... " + i);
		}
	}
}
public class ThreadDemo {
	public static void main(String[] args) {
		// C:创建任务对象
		MyTask mt = new MyTask();
		// D:创建Thread对象,并且把任务对象作为参数传递
		Thread t1 = new Thread(mt,"杰克");
		Thread t2 = new Thread(mt,"Rose");
		// E:启动线程
		t1.start();
		t2.start();
	}
}

        2.2.3、 实现原理

        方式1:我们自定义类,继承Thread,称为了线程类。现在我们start启动这个线程,JVM自动的调用这个线程的run方法。

        方式2:我们自定义类,实现Runnable接口,然后我们创建了Thread类对象,然后我们start启动了这个线程,JVM会自动的调用线程的run方法,也就是Thread中的run方法。但是,结果确实我们的Runnable实现类的run被执行了,为什么?

        2.2.4、方式二的好处

        A:方式二避免了Java单继承的局限性。

        B:将线程的操作代码和线程的任务代码分离了,解耦合。代码的扩展性更好,重用性更好。

        C:方式二可以更方便和灵活的实现数据的共享。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

攻城狮·建哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值