-------android培训、java培训、期待与您交流!----------
多线程是指在一个线程里通过多个执行单元各自执行对应的内容的技术。
1.1 进程:
进程就是一个正在执行的程序实例。即可以分配给处理器并由处理器执行的一个实体。需要强调进程是一个“执行中的”程序,只有处理器赋予这个程序以活动能力,它才能称为一个活的程序实体,即进程。
每一个进程都被系统赋予它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存放处理器执行的代码,数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
1.2 线程:
线程是进程运行中的一个执行路径。
1.3 进程和线程的区别:
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
进程有独立的地址空间,一个进程崩溃后,不会对其他进程造成影响;
而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。
所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
总的来说,线程依附进程的地址空间而存在,线程是进程执行路径。而同时进程必须保证线程的顺利执行从而保证进程自身的健壮(即不面临崩溃)。一个进程中可以有多个执行路径,就是多线程。
1.4 多线程的利弊:
多线程的好处:解决了多部分代码同时运行的问题。
多线程的弊端:因为虽然说是多线程,但是多个线程同时执行的实质的CPU做着快速切换完成。单个CPU每次只能执行一个线程这个是不会变的。而且这个切换是随机的,具有不稳定性。所以线程太多的话,会导致运行效率降低。
PS:JVM启动时启动了多条线程,至少有两条是明确的:执行主程序main函数的线程;负责回收垃圾的线程。而一个具体的进程中至少要有一个线程运行,即主线程main。
2 线程建立
2.1 线程建立的方法一:继承Thread类,
2.1.1,定义一个类继承Thread类。Thread是线程的大类,拥有多种面向线程的操作方法,供子类运用。
2.1.2,覆盖Thread中的run(){}方法。用于存放该线程需要执行的内容。即该线程的“任务”
2.1.3,直接创建该类的实例对象,创建线程。
2.1.4,调用start方法开启该线程并调用线程的run执行任务。
class Day12
{
public static void main(String[] args)
{
Demo t1 = new Demo(); //建立线程,但未启动
t1.start(); //线程启动;
Demo t2 = new Demo(); //建立线程2,
t2.start(); //线程2启动
}
}
class Demo extends Thread
{
int x = 0;
public void run(){
for (;x<= 10;x++){
System.out.println(this.getName()+"..."+x);
}
}
}
Thread-1...0
Thread-0...0
Thread-1...1
Thread-0...1
Thread-1...2
Thread-0...2
Thread-1...3
Thread-1...4
Thread-0...3
Thread-1...5
Thread-0...4
Thread-0...5
Thread-0...6
Thread-1...6
Thread-0...7
Thread-0...8
Thread-0...9
Thread-0...10
Thread-1...7
Thread-1...8
Thread-1...9
Thread-1...10
①其中this.getName语句获取当前线程的线程名。
②每个线程都有系统默认的名字Thread-0,-1,...
③可以看到线程0和线程1的执行无序的。jvm是随机调用线程,会出现较长时间内只操作一个线程的情况。
④start语句执行,则获取了可运行状态,一旦线程获取了执行权,则自动调用run语句,执行”任务“。
而单线程:
class Day12{
private String name;
Day12(String name){this.name = name;}
public static void main(String[] args){
Day12 d = new Day12("zhangsan");
Day12 d1 = new Day12("lisi");
d.demo();
d1.demo();
}
void demo(){
for (int x= 1; x<=5; x++){
System.out.println(name+"..."+x);
}
}
}
zhangsan...1
zhangsan...2
zhangsan...3
zhangsan...4
zhangsan...5
lisi...1
lisi...2
lisi...3
输出为语句顺序。d.demo()完成后它的”任务“循环后才执行d1.demo()。
2.2 线程建立的方法二:实现Runnable接口。
2.2.1,定义类实现Runnable接口。
2.2.2,覆盖接口中的run()方法,同方法一,储存线程要执行的任务。
2.2.3,通过Thread类创建的线程对象,并将Runnbale接口的子类对象(可以创建对象,或者用匿名对象)传入Thread类的构造函数里的参数中。
这是因为Thread类其中一个构造方法是输入Runnable作为参数。目的是让该Thread对象明确运行的内容。
class Day12{
public static void main(String[] args){
Demo d = new Demo();
Thread t = new Thread(d);
t.start();
Thread t2 = new Thread(d);
t2.start();
}
}
class Demo implements Runnable{
public void run(){
for (int x=1; x<=10; x++){
System.out.println(Thread.currentThread().getName()+"..."+x);
}
}
}
Thread-0...1
Thread-1...1
Thread-0...2
Thread-1...2
Thread-0...3
Thread-1...3
Thread-0...4
Thread-0...5
Thread-0...6