【概念】
进程:
正在运行的程序叫做进程。比如,我开了一个QQ,那么QQ在内存中就占了一块内存。
线程:
进程是不直接执行的,执行程序由线程来执行。进程只是负责分配内存控件。线程是执行路径(控制单元)。
一个进程中可以多执行路径,称之为多线程
一个进程中至少要有一个线程
而多线程的运行是由cpu来切换处理的,这个切换的时间是很短的。
其实应用程序的执行都是cpu在做着快速切换完成的。这个切换是随机的。
【多线程的好处和弊端】
好处:多部分代码同时执行
弊端:线程太多会影响cpu的处理效率。
【创建线程的方式】
方式一:继承Thread类。
步骤:
1.定义一个类继承Thread类
2.覆盖Thread类中的run方法
3.直接创建Thread的子类对象创建线程。
4.调用start()方法开启线程并调用线程的任务run方法执行。
class Demo extends Thread{
public void run(){
//执行的逻辑代码
}
}
Demo d=new Demo();
d.start();
创建线程的目的是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行,
而运行的指定代码就是这个执行路径的任务。jvm创建的主线程的任务都定义在了主函数中。
而自定义的线程它的任务在哪儿呢?
Thread类用于描述线程,线程是需要任务的。所以Thread类也是对任务的描述。
这个任务就通过Thread类中的run方法来体现。也就是说,run方法就是封装自定义线程运行任务的函数。
run方法中定义就是线程要运行的任务代码。
开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法。
将运行的代码定义在run方法中即可。
【线程的名称】
可以通过Thread的getName获取线程的名称 Thread-编号(从0开始)
Thread一创建就被编号了。
可以通过Thread.currentThread()获取到当前正在运行的线程对象。
修改线程的名字。可以在构造方法中
调用的父类的构造方法,把名称传进去就可以了
class Demo extends Thread{
Demo(String name){
super(name);
}
}
【线程的状态】
ps:临时阻塞状态:具备执行资格,不具备执行权,正在等待执行权。
只有被cpu切换到的线程才有执行权,其他线程都是处于阻塞状态。
sleep、wait()中的线程处于阻塞状态,所以运行状态的线程也有可能处于阻塞状态
1.被创建
start();
sleep(time)、wait()-用notify()唤醒
2.运行:具备着执行资格,具备执行权---------------------------------------------》冻结 :释放执行权的同时释放执行资格
run方法结束
线程的任务结束
stop()
3.消亡
【创建线程的第二种方式】
1.定义Runnable接口
2.覆盖接口中的run方法,将线程的任务代码封装到run方法中。
3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数传递。
为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。
4.调用线程对象的start方法开启线程
class Demo extends Runnable{
public void run(){
for(int i=0;i<10;i++){
}
}
}
main中:
Thread t=new Thread(new Runnable());
t.start();
细节:
Thread t=new Thread(new Runnable());
【使用Runnable的好处】
1.将线程的任务从线程的子类中分离出来,进行单独的封装。按照面向对象的思想将任务封装成对象。
2.避免类java单继承的局限性。
所以,创建线程的第二种方式较为常用。