多线程——小白理解
多线程
1 、程序、进程与线程:
程序、进程与线程:
程序:存放在磁盘上的一系列代码与数据的执行映像,是一个静止的实体;
进程:具有一定独立功能的程序,关于某个数据集合上的一次运动,是系统进行资源分配的和调度的一个独立单位。执行中的一个程序,是动态的实体。
线程:是进程的哟个实体,是CPU调度和分配的基本单位,也是比进程更小的能独立运行的基本单位。
1.1进程与线程
1、划分的尺度:线程更小,一个进程至少有一个线程或多个线程;
2、资源的分配:进程是资源分配的基本单位,进程内的线程共享其资源;
3、地址空间的划分:进程拥有独立的空间,进程内的线程共享空间;
4、处理器的调度:线程是处理器调度的基本单位;
5、执行:线程是程序的入口,每一个线程都有一个程序入口,但线程不能单独执行,必须组成进程,进程又必须有主线程。——一个程序必须有一个进程(可以多个),一个进程必须有一个线程(可以多个)。
1.2 进程和程序
1.2.1 进程和程序的区别
1、程序只是一组指令的有序集合,没有任何含义,是静态的实体。进程是数据集上的执行,是动态的。
2、进程与程序不一一对应,程序在不同数据集上就是不同的进程,进程控制可以唯一对其进行标识。程序不可以,程序与数据集之间没有联系,它仅仅只是指令集。
3、进程具有并发性和交往性,程序有封闭性。
1.2.2 进程和程序之间的联系
1、进程是动态实体,有周期,而程序的指令集控制了整个进程在数据集上执行的全过程。
2、一个进程必定对于一个程序,而一个程序不一定对于进程(没执行的状态下),也可能对于这多个进程。
2 、 多线程
在程序的底层多个线程同时执行,在表面上看起来是同一个CPU执行了多个任务。其中的一个任务为一个线程(thread),能同时运行1一个以上线程的程序为多线程程序。
3 、thread类
extends Objectimplements Runnable
线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
创建对象:Thread thread = new Thread();
常用方法:
long getId()==>返回该线程的标识符。
String getName() ==> 返回该线程的名称
void setName(String name)==> 改变线程名称,使之与参数 name 相同。
static void sleep(long millis) ==>在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
void start() ==> 使该线程开始执行;Java 虚拟机调用该线程的 run 方法
package thread;
//测试多线程 thread
public class Test_Thread {
public static void main(String[] args) throws InterruptedException {
//创建对象
Thread thread = new Thread();
//调用方法
System.out.println(thread.getId());//返回线程的标识符(long类型)
System.out.println(thread.getName());//返回线程的名称(string类型)
thread.run();
thread.setName("xianchengyi");//设置线程的名称
System.out.println(thread.getName());
thread.start();//开始线程
thread.stop();//结束线程
thread.sleep(500);//在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
//获取当前正在执行任务的线程对象的一个引用
Thread thread1 = Thread.currentThread();
System.out.println(thread1.getName());
/**结果显示
* 11
* Thread-0
* xianchengyi
* main
*/
}
}
3.1 构建Thread派生类对象
程序中,线程都是Thread类的实例对象,创建Thread实例对象和控制自己的多线程(演示两个线程)。完成线程真正功能的代码应位于类的run方法中,一个类继承了Thread类后,应重写run方法,将代码放入该方法中。同时调用Thread类中start()方法执行线程。
执行一个线程时,就自动产生一个线程,主方法在这个线程上运行,不在启动其他线程时就是单线程。主方法这个线程由Java虚拟机负责,操作人员负责启动自己的线程。
package thread;
//多线程测试(复杂thread)
public class Test1_thread {
public static void main(String[] args) {
//创建对象
Person person = new Person();
//调用方法
person.setName("线程一");
person.start();
//模拟多线程
Person person1 = new Person();
person1.setName("线程二");
person1.start();
/**结果显示:随机的,由CPU调度
* 线程二========0
* 线程一========0
* 线程二========1
* 线程一========1
* 线程一========2
* 线程一========3
* 线程一========4
* 线程一========5
* 线程一========6
* 线程一========7
* 线程二========2
* 线程一========8
* 线程二========3
* 线程一========9
* 线程二========4
* 线程二========5
* 线程二========6
* 线程二========7
* 线程二========8
* 线程二========9
*/
}
}
//定义线程并继承thread类
class Person extends Thread {
public void out(){
System.out.println("多线程输出!");
}
@Override//重写run方法
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println(super.getName()+"========"+i);
}
}
}
4、 Runnable接口的对象构建Thread对象
处理多线程的第二中方法就是实习Runnable接口。
//语法结构为:
class Student implements Runnable{//student 自定义类名||在student后面可以加(extends Object),因为都是继承Object类。最后实现接口
@Override//必须重写run方法
public void run() {
//实现方法体
//就是代码块
}
}
使用Runnable接口启动新线程步骤:(与Thread类区别挺大,它自己没有任何方法去启动,只能通过Thread的方法来启动)
1 、创建Runnable对象;
2 、 使用参数为Runnable对象的构造方法创建Thread实例;
3、 调用start()方法启动线程。
package thread;
//测试runnable 接口
public class Test_Runnable {
public static void main(String[] args) {
Student student = new Student();
// student.run();//Runnable 中只能使用run方法
//使用参数为Runnable对象的构造方法创建Thread实例;
Thread thread = new Thread(student);
Thread thread1 = new Thread(student);
//修改线程名称,方便对比
thread.setName("线程一");
thread1.setName("线程二");
//启动线程
thread.start();
thread1.start();
/**实例结果,如果是顺序的,可以把范围扩大一点
*线程二====0
* 线程一====0
* 线程二====1
* 线程一====1
* 线程一====2
* 线程一====3
* 线程一====4
* 线程一====5
* 线程一====6
* 线程二====2
* 线程二====3
* 线程二====4
* 线程二====5
* 线程二====6
* 线程二====7
* 线程二====8
* 线程二====9
* 线程二====10
* 线程二====11
* 线程一====7
* 线程二====12
* 线程二====13
* 线程二====14
* 线程一====8
* 线程一====9
* 线程一====10
* 线程一====11
* 线程一====12
* 线程一====13
* 线程一====14
*/
}
}
class Student implements Runnable{
@Override//必须重写run方法
public void run() {
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName()+"===="+i);
}
}