【JavaEE】多线程

线程

在Java中,鼓励多线程编程。进程可以满足并发编程,但是效率不高(创建、销毁、调度时间都比较长,这些都消耗在申请资源上了),而线程就不一样。

线程也叫"轻量级进程",创建、销毁、调度都更快。但是它不能独立存在,而是依附于进程(也就是说进程包含线程),一个进程可以一个或多个线程,前面谈到的进程调度都是基于一个进程只有一个线程的情况下,实际上一个进程有多个线程,每个线程都是可以独立调度的,每个线程也有状态、优先级、上下文、记账信息,每个PCB对应到每个线程上,pid是与进程共用同一份的(内存指针、文件描述符表也是)。

总的来说就是:进程包含线程-》一个进程由多个PCB共同表示-》每个PCB就用来表示一个线程-》每个线程有自己的状态、优先级、上下文、记账信息-》每个线程都可以独立的去CPU上调度执行-》这些PCB共用了同样的内存指针、文件描述符表-》创建线程/PCB不需要重新申请资源-》创建销毁效率更高

总结线程特点

  1. 每个线程都可以独立的去CPU上调度执行。
  2. 同一个进程的多线程之间共用同一份内存空间、文件资源......(所以创建线程就不需要重新申请资源,直接复用进程的资源,使得线程速度更快)
  • 然而不是线程越多效率越快,当增加到一定数目时,效率无法提升,反而会调度线程太多,使调赴花销更大 。
  • 当两个线程同时访问变量时也会出现问题,线程不安全问题。
  • 如果某个线程出现异常:一个线程抛出异常,如果没有妥善处理就容易把整个进程崩溃。

进程与线程的区别(重点)

  1. 进程包含线程;
  2. 进程和线程都是实现并发并发编程,但是线程比进程更高效、轻量;
  3. 同一个进程的线程之间共用一份资源(内存+硬盘),省去资源的开销;
  4. 进程和进程之间是独立的,线程和线程(同一个进程中)可能会相互影响;
  5. 进程时资源分配的基本单位,线城市调度执行的基本单位;

多线程

Java如何进行多线程编程的?

线程是操作系统的概念,操作系统提供一些API可以操作线程,Java针对API进程封装。Thread类就是操作系统提供的API进行封装和抽象。

1.多线程程序

复制代码
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new MyThread();
        t.start();
        while (true){
            sleep(1000);
            System.out.println("hello main");
        }
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        while (true) {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("hello thread");
        }
    }
}

上面这个程序运行就可以看到,这两个线程是"同时执行"的,看到的结果是两边的日志都在交替打印,---》可以得到的是每个线程都是独立执行的逻辑(独立的执行流)

start可以创建一个新的线程,如果将start改成run,此时代码就不会创建新线程,只有主线程,这个主线程只能执行完run,才能往后继续执行。

上面是使用idea观察多线程,也可以通过 jconsole (jdk-》bin-》jconsole.exe)来观察进程里的多线程,如果不知道jdk安装在哪个路径下可以通过idea寻找。

然后再双击 jconsole.exe 出现以下页面,,如果没有出现以下页面那就是没有以管理员身份打开

2.创建线程

1.继承Thread,重写run

1)继承Thread来创建一个线程类;2)创建线程类的实例;3)调用start方法启动线程

继承Thread类,需要重写它里面的run方法,想要看到"同时"的效果,就需要使用sleep,之前在学C语言中的sleep,现在Thread类中有自己的sleep方法,使用Thread中的sleep会出现异常,需要解决异常可以抛出异常或者try/catch异常,如果是重写父类的run方法,父类的run方法没有throws,子类方法也就不能有,所以只能try/catch异常。main方法中就可以使用throws也可以使用try/catch。操作系统对于多个线程的调度顺序是不确定的/"随机的",运行结果取决于操作系统对线程调度的模块(调度器)

2.实现Runnable,重写run

1)实现Runable接口;2)创建Thread类实例,调用Thread的构造方法是将Runable对象作为target参数;3)调用start方法;

使用Runnable 的写法,和直接继承Thread 之间的区别就是解耦合(两个线程之间的关联程度)

3. 继承Thread,重写run(使用匿名内部类)

使用匿名内部类创建Thread子类对象

4.实现Runnable,重写run(使用匿名内部类)

使用匿名内部类创建Runnable子类对象

5.基于 lambda 表达式(推荐使用)

lambda表达式中直接重写run方法中的内容,不用再继承实现哪个类或者哪个接口。

3.Thread 的其他构造方法

Thread()//创建线程对象

Thread(Runnable target)//使用Runnable对象创建线程对象

Thread(String name)//创建线程对象,并命名

Thread(Runnable target, String name) //使用Runnable对象创建线程对象,并命名

4.Thread 常见的属性

ID//身份标识 getId()//获取id

名称 getName()//获得线程名称

状态 getState()//获得当前状态

优先级 getPriority()

是否后台线程 isDaemon()

是否存活 isAlive()

是否被中断 isInterrupted()

后台线程:后台进程不结束不影响整个进程的结束。

前台线程:如果前台线程没有执行结束,此时整个进程是一定不会结束的。

Thread 对象往往比系统中的线程更长,线程没了Thread 对象还在。

相关推荐
陳長生.8 小时前
JAVA EE(进阶)_HTML
javascript·css·java-ee·html
我命由我123451 天前
Android 动态申请 REQUEST_INSTALL_PACKAGES 权限问题:申请权限失败
android·java·开发语言·java-ee·android studio·android jetpack·android-studio
苦学编程的谢1 天前
多线程进阶
java·开发语言·java-ee
界面开发小八哥2 天前
「Java EE开发指南」如何使用MyEclipse的可视化JSF编辑器设计JSP?(二)
java·ide·人工智能·java-ee·myeclipse
purrrew2 天前
【Java ee初阶】jvm(2)
java·jvm·java-ee
陳長生.2 天前
JAVA EE(进阶)_进阶的开端
java·java-ee
purrrew2 天前
【Java ee初阶】jvm(1)
java·jvm·java-ee
SuperherRo2 天前
Web开发-JavaEE应用&SpringBoot栈&SnakeYaml反序列化链&JAR&WAR&构建打包
前端·java-ee·jar·反序列化·war·snakeyaml