0
点赞
收藏
分享

微信扫一扫

JavaEE-多线程(一)

线程是什么?为什么要有线程?进程和线程的区别?

  1. 一个线程就是一个”执行流“,多个线程之间按照自己的顺序执行代码。多个线程之间执行多份代码;
  2. “并发编程”,线程比进程更加轻量;
  3. 进程包含线程,每个进程里面至少含有一个线程;进程之间内存独立,资源不共享,进程的线程之间内存相同,资源共享;进程是系统资源分配的最小单位,线程是系统调度的最小单位。

一、创建线程

JavaEE-多线程(一)_Thread方法

//重写run方法:
//明确代码索要执行的内容是什么;

//thread.start
//此处才表示开始创建线程;操作系统中会创建对应的PCB,
//然后PCB会加入到系统链表中参与调度;

以上代码在执行那个过程中会发现:“hello world”与“hello mythread”的出现没有规律:

  • 每个线程都是独立的执行流,main和my thread两个执行流互不干扰,并发执行;
  • 由于操作系统调度器的是随机调度的,因此两个线程之间执行是随机的;

上述代码中将thread.start改为thread.run后,
会发现只执行MyThread中的代码,而不再执行main方法中的代码
//原因:
//使用start会是两个线程进行并发执行
//直接调用run并没有创建新的进程,而是在之前的进程中执行了run里面的内容;
//使用start创建了新进程,在新进程里面会调用run,新、旧线程之间是并发执行

二、创建进程的方法

  • 类继承thread,重写run方法;
  • 类接口Runnable,重写run方法;
  • 类继承thread,匿名内部类;
  • Runnable,匿名内部类;
  • lamnda表达式;

类接口Runnable,重写run方法:

JavaEE-多线程(一)_线程状态_02

通过实现Runnable接口,重写run方法;
Runnable实例化myRunnable对象后,通过

类继承thread,匿名内部类:

JavaEE-多线程(一)_线程状态_03

//Thread thread = new Thread()
//此处创建匿名内部类,这个内部类是Thread的子类,因此重写run方法;
//此时操作系统还没有创建线程

//thread.start();
//此处才真正创建了线程

Runnable,匿名内部类:

JavaEE-多线程(一)_join方法_04

lambda表达式:

JavaEE-多线程(一)_Thread方法_05

三、详解Thread方法

常见的属性:

通过Thread创建thread;
System.out.println(thread.getId());
System.out.println(thread.getName());
System.out.println("线程状态:" + thread.getState());
System.out.println("线程是否存活:" + thread.isAlive());
System.out.println("线程优先级:" + thread.getPriority());
System.out.println("是否是后台线程:" + thread.isDaemon());
System.out.println("线程是否被中断:" + thread.isInterrupted());

3.1、前台线程与后台线程

注意:当创建一个线程的时候,线程会默认为前台线程,而前台线程与后台线程的区别在于:前台线程会阻止进程结束,只有当前台线程结束的时候,进程才会结束,而后台线程则不会阻止进程结束,即使后台进程没有执行完,进程也会直接结束。

JavaEE-多线程(一)_join方法_06

JavaEE-多线程(一)_多线程_07

3.2、启动线程和结束线程

启动线程:
当使用Thread实例thread的时候并没有在系统中创建一个线程,
只有当thread.start的时候才真正的在系统中创建一个线程。

结束线程:

  1. 直接是用自己定义的标志位来结束线程;
  2. 使用Thread自带的标志位;

//第一种:::
public class Test3 {
public static boolean isQuit = false;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()-> {
while(!isQuit){
System.out.println("线程执行中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
Thread.sleep(5000);
System.out.println("线程即将退出...");
isQuit = true;
}
}
//首先定义一个布尔类型变量并设置为false
//当代码执行到最后时会设为为true,此时while里面的逻辑去反会判定为false
//因此代码执行结束

//第二种:::
关于interrupt方法:
//当线程没有处于阻塞的状态时,interrupt会修改内置的标记位;
//当线程正在处于阻塞的状态时,此时interrrupt会让线程内部产生阻塞的方法(例如sleep)抛出异常

JavaEE-多线程(一)_Thread方法_08

上述代码抛出异常是由于线程处于阻塞状态(由于调用sleep),因此interrupt方法会控制sleep,让sleep抛出异常;

抛出异常时,可以控制异常的行为:
1、立即退出;
2、稍后退出;
3、不用退出;

JavaEE-多线程(一)_join方法_09

四、join方法

在java中,为了等待其他线程结束而设定的一个方法;

代码执行过程中可以通过join来控制代码结束的顺序!!!

JavaEE-多线程(一)_Thread方法_10

join方法:

如果被等待的程序已经执行完,则直接返回;

如果被等待的程序没有执行完,则阻塞等待。

五、线程的状态

线程的五种状态:

  • NEW:创建新线程,但是还未开始执行;
  • RUNNABLE:可以执行代码,又分为执行中和即将开始执行;
  • BLOCKED:等待执行;
  • WAITING:等待执行;
  • TIMED_WAITING:等待执行;
  • TERMINATED:执行完成;

JavaEE-多线程(一)_多线程_11

线程状态之间的相互转换主要是通过RUNNABLE代码实现的;

补充:关于进程的“休眠”

JavaEE-多线程(一)_Thread方法_12

在就绪队列中,这里的PCB是可以进入CPU当中进行运行的,而在阻塞队列中,这里面的PCB暂时不参与系统的调度;

当就绪队列中的某一个线程被执行休眠指令后(例如sleep(1000ms))则会进入到阻塞队列中,在阻塞队列中休眠对应的时间后会重新进入到就绪队列中,但这里并不是说进入就绪队列就可以立即执行,什么时候执行取决于调度器。

拓展:关于“PCB”

一个进程包含多个线程,每个线程对应一个PCB,因此一个进程就对应一组PCB,而同一组的若干个PCB当中有“线程组id”,在同一个进程中值是一样的。另外,PCB里面的内存指针和文件描述符表也是同一份。


































举报

相关推荐

0 条评论