一、线程与进程
1、进程:
是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
2、线程:
线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
也就是说,一个软件中至少有一个应用程序,应用程序的一次运行就是一个进程,一个进程中至少有一个线程。
二、并发与并行
1、并行:
指两个或多个事件在同一时刻发生(同时发生)。指在同一时刻,有多条指令在多个处理器上同时执行。
2、并发:
指两个或多个事件在同一时间段内发生。指在同一个时刻只能有一条指令执行,但多个进程的指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。例如:抢票、电商秒杀。
三、线程调度
1、分时调度:
所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
2、抢占式调度:
优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性)。Java使用的为抢占式调度。
四、线程状态的方法
1、休眠:sleep()
2、让步:yield()
3、插队:join()
(一)线程休眠
1、测试类(新年倒计时):
调用Thread.sleep(),方法时,要捕获异常。
括号内部是放的类型是整数,表示休眠的毫秒数。1000毫秒 = 1秒。
//2022.7.29
public class ThreadMethod3 {
public static void main(String[] args) {
//新年倒计时中,使用线程休眠的方法
System.out.println("新年倒计时,开始");
//使用for循环,进行倒计时
for (int i = 10; i >=1; i--) {
System.out.println(i);
//输出一个数时,暂停一秒
/*这个sleep休眠方式会出现异常,在主程序中不建议抛出异常
* 主程序尽可能使用try...catch
* */
//选中要放入try内部的代码,按快捷键“Ctrl+Alt+t”,选择try...catch
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("新年快乐");
}
}
线程休眠测试结果:
结果表明:数字每隔一秒才会出现。
(二)线程让步
1、测试类:
(1)自定义的线程使用匿名内部类创建,重写父类Thread的run()方法。
(2)主函数中创建了另一个线程,在其中调用线程的让步方法Thread.currentThread().yield();
//2022.7.29
public class ThreadMethod4 {
public static void main(String[] args) {
//测试线程中的yield方法
//先自定义一个线程,使用匿名内部类,用Thread类的对象进行接收
Thread t = new Thread(new Runnable() {
@Override
//重写run方法
public void run() {
//输出0-20内的偶数
for (int i = 0; i <= 20; i += 2) {
//输出当前线程对象的名称与偶数值
System.out.println("当前线程对象的名称" + Thread.currentThread().getName()
+ ",偶数线程:" + i);
}
}
});
//启动线程
t.start();
//在设置一个主函数的线程,用于打印0-20内的奇数值
for (int i = 1; i <= 20; i += 2) {
System.out.println("奇数线程:" + i);
//此处测试线程状态方法yield()
//作用是让当前线程暂停一下,当前线程暂停一下,让出CPU,下次两个线程任然使用抢占式调度获得CPU的使用权
Thread.currentThread().yield();
}
}
}
线程让步测试结果:
结果表明:线程让步yield(),使当前的线程暂停一下,让出CPU,但是下一次CPU还是可能会调用它。
(三)线程插队
1、测试类:
(1)自定义的线程使用匿名内部类创建,重写父类Thread的run()方法。
(2)主函数中创建了另一个线程,在其中调用线程的插队方法,此时调用插队方法的对象是先执行线程的对象,如:t.join();
(3)调用插队方法时,需要捕获异常。
(4)异常:
①产生异常时,可使用采用的解决方式是:try...catch(异常类型 变量名)..finilly...或throws
②若try中没有异常,那么catch中的代码不会执行,但finilly中的代码会执行。若try中的代码发生异常,那么catch中进行异常捕获,可使用多个catch。
//2022.7.29
public class ThreadMethod5 {
public static void main(String[] args) {
//测试线程状态方法的join()方法
//先自定义一个线程,使用匿名内部类,用Thread类的对象进行接收
Thread t = new Thread(new Runnable() {
@Override
//重写run方法
public void run() {
//输出0-20内的偶数
for (int i = 0; i <= 20; i += 2) {
//输出当前线程对象的名称与偶数值
System.out.println("偶数线程:" + i);
}
}
});
//启动线程
t.start();
//在设置一个主函数的线程,用于打印0-20内的奇数值
for (int i = 1; i <= 20; i += 2) {
//当i=3时,测试join()方法
if(i == 3){
//join()使这个线程停止,执行其他线程完成后再继续
//直接调用join()方法,会报错,需要捕获异常
try {
//注意:此处调用join()方法的对象,是先要执行的线程对象
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("main:" + i);
}
}
}
线程插队测试结果:
结果表明,插队join()方法调用后,当符合判断条件时,会先执行另一个线程,等待另一个线程执行结束后,才会再次执行原来的线程。