for循环多线程执⾏_内容细致!⼀问彻底帮你掌握多线程,线
thread技术程创建,先收藏后观看!...
多线程介绍
学习多线程之前,我们先要了解⼏个关于多线程有关的概念。
进程:进程指正在运⾏的程序。确切的来说,当⼀个程序进⼊内存运⾏,即变成⼀个进程,进程是处于运⾏过程中的程序,并且具有⼀定独⽴功能。
线程:线程是进程中的⼀个执⾏单元,负责当前进程中程序的执⾏,⼀个进程中⾄少有⼀个线程。⼀个进程中是可以有多个线程的,这个应⽤程序也可以称之为多线程程序。
简⽽⾔之:⼀个程序运⾏后⾄少有⼀个进程,⼀个进程中可以包含多个线程
什么是多线程呢?即就是⼀个程序中有多个线程在同时执⾏。
通过下图来区别单线程程序与多线程程序的不同:
l 单线程程序:即,若有多个任务只能依次执⾏。当上⼀个任务执⾏结束后,下⼀个任务开始执⾏。如,去⽹吧上⽹,⽹吧只能让⼀个⼈上⽹,当这个⼈下机后,下⼀个⼈才能上⽹。
l 多线程程序:即,若有多个任务可以同时执⾏。如,去⽹吧上⽹,⽹吧能够让多个⼈同时上⽹。
程序运⾏原理
l 分时调度
所有线程轮流使⽤ CPU 的使⽤权,平均分配每个线程占⽤ CPU 的时间。
l 抢占式调度
优先让优先级⾼的线程使⽤ CPU,如果线程的优先级相同,那么会随机选择⼀个(线程随机性),Java使⽤的为抢占式调度。
在这⾥插⼊图⽚描述
抢占式调度详解
⼤部分操作系统都⽀持多进程并发运⾏,现在的操作系统⼏乎都⽀持同时运⾏多个程序。⽐如:现在我们上课⼀边使⽤编辑器,⼀边使⽤录屏软件,同时还开着画图板,dos窗⼝等软件。此时,这些程序是在同时运⾏,”感觉这些软件好像在同⼀时刻运⾏着“。
实际上,CPU(中央处理器)使⽤抢占式调度模式在多个线程间进⾏着⾼速的切换。对于CPU的⼀个核⽽⾔,某个时刻,只能执⾏⼀个线程,⽽ CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同⼀时刻运⾏。
其实,多线程程序并不能提⾼程序的运⾏速度,但能够提⾼程序运⾏效率,让CPU的使⽤率更⾼。
主线程
回想我们以前学习中写过的代码,当我们在dos命令⾏中输⼊java空格类名回车后,启动JVM,并且加载对应的class⽂件。虚拟机并会从main⽅法开始执⾏我们的程序代码,⼀直把main⽅法的代码执⾏结束。如果在执⾏过程遇到循环时间⽐较长的代码,那么在循环之后的其他代码是不会被马上执⾏的。如下代码演⽰:
class Demo{
String name;
Demo(String name){
this.name = name;
}
void show() {
for (int i=1;i<=10000 ;i++ ) {
System.out.println("name="+name+",i="+i);
}
}
}
class ThreadDemo {
public static void main(String[] args) {
Demo d = new Demo("⼩强");
Demo d2 = new Demo("旺财");
d.show();
d2.show();
System.out.println("Hello World!");
}
}
若在上述代码中show⽅法中的循环执⾏次数很多,这时在d.show();下⾯的代码是不会马上执⾏的,并且在dos窗⼝会看到不停的输出name=⼩强,i=值,这样的语句。为什么会这样呢?
原因是:jvm启动后,必然有⼀个执⾏路径(线程)从main⽅法开始的,⼀直执⾏到main⽅法结束,这个线程在java中称之为主线程。当程序的主线程执⾏时,如果遇到了循环⽽导致程序在指定位置停留时间过长,则⽆法马上执⾏下⾯的程序,需要等待循环结束后能够执⾏。
那么,能否实现⼀个主线程负责执⾏其中⼀个循环,再由另⼀个线程负责其他代码的执⾏,最终实现多部分代码同时执⾏的效果?
能够实现同时执⾏,通过Java中的多线程技术来解决该问题。
Thread类
该如何创建线程呢?通过API中搜索,查到Thread类。通过阅读Thread类中的描述。Thread是程序中的执⾏线程。Java 虚拟机允许应⽤程序并发地运⾏多个执⾏线程。
l 构造⽅法
l 常⽤⽅法
继续阅读,发现创建新执⾏线程有两种⽅法。
l ⼀种⽅法是将类声明为 Thread 的⼦类。该⼦类应重写 Thread 类的 run ⽅法。创建对象,开启线程。run⽅法相当于其他线程的main⽅法。
l 另⼀种⽅法是声明⼀个实现 Runnable 接⼝的类。该类然后实现 run ⽅法。然后创建Runnable的⼦类对象,传⼊到某个线程的构造⽅法中,开启线程。
创建线程⽅式⼀继承Thread类
创建线程的步骤:
1 定义⼀个类继承Thread。
2 重写run⽅法。
3 创建⼦类对象,就是创建线程对象。
4 调⽤start⽅法,开启线程并让线程执⾏,同时还会告诉jvm去调⽤run⽅法。
public class Demo01 {
public static void main(String[] args) {
//创建⾃定义线程对象
MyThread mt = new MyThread("新的线程!");
//开启新线程
mt.start();
//在主⽅法中执⾏for循环
for (int i = 0; i < 10; i++) {
System.out.println("main线程!"+i);
}
}
}
l ⾃定义线程类
public class MyThread extends Thread {
//定义指定线程名称的构造⽅法
public MyThread(String name) {
/
/调⽤⽗类的String参数的构造⽅法,指定线程的名称
super(name);
}
/**
* 重写run⽅法,完成该线程执⾏的逻辑
*/
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+":正在执⾏!"+i);
}
}
}
思考:线程对象调⽤ run⽅法和调⽤start⽅法区别?
线程对象调⽤run⽅法不开启线程。仅是对象调⽤⽅法。线程对象调⽤start开启线程,并让jvm调⽤run⽅法在开启的线程中执⾏。
继承Thread类原理
我们为什么要继承Thread类,并调⽤其的start⽅法才能开启线程呢?
继承Thread类:因为Thread类⽤来描述线程,具备线程应该有功能。那为什么不直接创建Thread类的对象呢?如下代码:
Thread t1 = new Thread();
t1.start();//这样做没有错,但是该start调⽤的是Thread类中的run⽅法,⽽这个run⽅法没有做什么事情,更重要的是这个run⽅法中并没有定义我们需要让线程执⾏的代码。
创建线程的⽬的是什么?
是为了建⽴程序单独的执⾏路径,让多部分代码实现同时执⾏。也就是说线程创建并执⾏需要给定线程要执⾏的任务。
对于之前所讲的主线程,它的任务定义在main函数中。⾃定义线程需要执⾏的任务都定义在run⽅法中。
Thread类run⽅法中的任务并不是我们所需要的,只有重写这个run⽅法。既然Thread类已经定义了线程任务的编写位置(run⽅法),那么只要在编写位置(run⽅法)中定义任务代码即可。所以进⾏了重写run⽅法动作。
多线程的内存图解
多线程执⾏时,到底在内存中是如何运⾏的呢?
以上个程序为例,进⾏图解说明:
多线程执⾏时,在栈内存中,其实每⼀个执⾏线程都有⼀⽚⾃⼰所属的栈内存空间。进⾏⽅法的压栈和弹栈。
当执⾏线程的任务结束了,线程⾃动在栈内存中释放了。但是当所有的执⾏线程都结束了,那么进程就结束了。
获取线程名称
开启的线程都会有⾃⼰的独⽴运⾏栈内存,那么这些运⾏的线程的名字是什么呢?该如何获取呢?既然是线程的名字,按照⾯向对象的特点,是哪个对象的属性和谁的功能,那么我们就去那个对象就可以了。查阅Thread类的API⽂档发现有个⽅法是获取当前正在运⾏的线程对象。还有个⽅法是获取当前线程对象的名称。既然到了,我们就可以试试。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论