1.进程和线程
1.计算机的操作系统大多采用多任务和分时设计,多任务指在一个操作系统可以同时运行多个程序。对于多个独立运行的任务,每个任务对应一个进程,一个进程又可以产生多个线程。
1.1 进程
1.程序:对数据描述和操作的代码的集合,如WPS、QQ等应用程序。
2.进程:程序的一次动态执行过程,即:加载代码-->执行代码-->执行完毕这样一个完整的过程。这个过程也是进程本身从产生、到发展、至消亡的一个过程。
3.操作系统同时管理一个计算机系统中的多个进程,让计算机系统中的多个进程轮流使用CPU资源,或者共享操作系统的其它资源。
4.进程有如下特点:
-->进程是系统运行程序的基本单位。
-->每一个进程都有自己独立的一块内存空间、一组系统资源。
-->每一个进程的内部数据和状态都是完全独立的。
1.2 线程
1.线程是进程中执行运算的最小单位,一个进程在其执行过程中可以产生多个线程,而线程必须在进程内执行。
2.线程是进程内部的一个执行单元,是可完成一个独立任务的顺序控制流程,如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为多线程。
3.线程按处理级别分为核心级线程和用户级线程。
核心级线程:和系统任务相关的线程,负责处理不同进程之间的多个线程。
用户级线程:由于程序的需要而编写的线程,这些线程的创建、执行和消亡都是编写在应用程序时进行控制的。
线程和进程之间的联系与区别:
一个进程中至少要有一个线程。
资源分配给进程,同一进程的所有线程共享该进程的所有资源。
处理机分配给线程,即真正在处理机上运行的是线程。
2.编写线程类
2.1 主线程
1.每个程序至少自动拥有一个线程,称为主线程。当程序加载到内存时启动主线程。
2.Java程序中的public static void main()方法是主线程的入口,运行java程序时,先执行这个方法
3.用户编写的线程一般都是指除了主线程之外的其他线程。
代码举例说明:
//main()是主线程入口,在主线程里进行子线程,最后关闭主线程
public static void main(String[] args) {
// 获取当前线程:currentThread()方法:是静态方法,返回一个Thread类对象
Thread thread=Thread.currentThread();
//getName()方法:返回当前线程的名称
String threadName=thread.getName();
System.out.println("当前线程的名称是:"+threadName);//当前线程的名称是:main
//setName()方法:设置当前线程的名称
thread.setName("开始线程");
System.out.println("当前线程的名称是:"+thread.getName());//当前线程的名称是:开始线程
//getPriority()方法:获取当前线程的优先级
System.out.println("当前线程的优先级是:"+thread.getPriority());//当前线程的优先级是:5
//toString()方法:返回该线程的字符串表示形式,包括线程名称、优先级和线程组
System.out.println(thread.toString());//Thread[开始线程,5,main]
//获取线程的优先级
System.out.println(Thread.MAX_PRIORITY);//最高优先级10
System.out.println(Thread.MIN_PRIORITY);//最低优先级1
System.out.println(Thread.NORM_PRIORITY);//默认优先级5
}
2.2 定义线程类
使用一个线程可以分为已下步骤:
1.定义一个线程,同时指明这个线程所要执行的代码;
2.创建线程对象;
3.启动线程;
4.终止线程。
定义一个线程类主要有两种方法,继承java.lang包的Thread类和实现java.lang包的Runnable接口。
2.2.1 继承Thread类创建线程类
Thread类提供了大量的方法来控制可操作线程,常用方法如下:
void run()//执行任务操作
void start()//启动线程,使该线程开始执行
void sleep(long millis)//在指定的毫秒数内让当前正在执行的线程休眠
String getName()//返回该线程的名称
int getPriority()//返回该线程的优先级
void setPriority(int newPriority)//设置线程的优先级
Tread.State getState()//返回该线程的状态
boolean isAlice()//测试线程是否处于活动状态
void join()//等待该线程终止
void interrupt()//中断线程
void yield()//暂停当前正在执行的线程对象,执行其他线程
1.创建线程类继承Thread类并重写Thread类的run()方法 ,线程要执行的操作代码都要写在run()方法中。
//通过继承Thread类来创建一个线程,需要在创建的线程类里重写run()方法
public class MyThread extends Thread {
// 在run()方法里写线程体,即要执行的操作代码
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
// Thread.currentThread().getName()获取当前线程对象的名字
System.out.println(Thread.currentThread().getName() + "->" + i);
}
}
}
2.在测试类中创建线程类对象并调用start()方法启动线程。
public static void main(String[] args) {
//创建线程对象
MyThread mt1=new MyThread();
MyThread mt2=new MyThread();
//设置线程名字
mt1.setName("第一个线程");
mt2.setName("第二个线程");
//线程优先级反映的是获取CPU资源的概率,优先级高的线程获取CPU资源的概率大一些,并不能保证优先级高的线程一定比优先级低的线程先获取CPU资源
mt1.setPriority(10);
mt1.setPriority(10);
mt2.setPriority(2);
//mt1.run();或者mt2.run();直接调用run()方法是启动main线程
//通过start()方法启动创建的线程
mt1.start();
mt2.start();
}
注意:多线程之间并不是并行运行,而是交替抢占CPU资源运行,哪个线程获取CPU资源就执行哪个线程。
2.2.2 实现Runnable接口创建线程类
1.Runnable接口中声明了一个run()方法,一个类可以通过实现Runnable接口并实现run()方法完成线程的所有活动,已实现的run()方法称为该对象的线程体。
//通过实现Runnable接口创建线程
public class MyThread implements Runnable {
//重写run()方法
@Override
public void run() {
for (int i = 0; i <=10; i++) {
System.out.println(Thread.currentThread().getName()+"->"+i);
}
}
}
2.任何一个实现Runnable接口的对象都可以作为一个线程的目标对象。
public static void main(String[] args) {
MyThread mt1=new MyThread();
//该构造方法需要传递两个参数:Runnable接口的实例化对象,当前线程名称
Thread thread1=new Thread(mt1, "第一个线程");
Thread thread2=new Thread(mt1, "第二个线程");
//start()方法是Thread类的方法,所以调用前需要先创建Thread类对象
thread1.start();
thread2.start();
}
继承Thread类VS实现Runnable接口
1.直接继承Thread类的方式编写简单,可以直接操作线程,适用于单根继承的情况;
2.实现Runnable接口避免了单根继承的局限性,并且使用实现Runnable接口的方法来创建线程,可以使多个线程之间使用同一个Runnable对象。