首页 > 编程语言 >JavaEE——多线程

JavaEE——多线程

时间:2024-09-24 18:50:51浏览次数:8  
标签:run Thread JavaEE 线程 进程 new 多线程 public

接着上篇博客我们已经学习了进程的相关概念,了解到进程里面的相关重要属性,那么这篇博客呢我们要学习一个新的知识点——线程!

一、引入进程的目的

首先引入进程这个概念,是为了解决“并发编程”这样的问题。因为CPU 再往小了做,比较困难了,这是因为 CPU 进入了多核心的时代,要想进一步提高程序的执行速度,就需要充分的利用 CPU 的多核资源。
但是呢,多进程编程,已经可以解决并发编程的问题了已经可以利用起来 cpu 多核资源了。

弊端:

进程太重了!(消耗资源多 & 速度慢)。
1、创建一个进程,开销比较大。
2、销毁一个进程,开销也比较大。

3、调度一个进程,开销也比较大。
说进程重,主要就是重在”资源分配/回收。

线程:

所以我们的线程也就应运而生.线程也叫做“轻量级进程"。
目的就是解决并发编程问题的前提下,让创建,销毁,调度的速度,更快一些!
轻的原因:主要是"把申请资源/释放资源"的操作给省下了。

二、多线程的优点

假设小帅开了一家工厂,他在这个工厂里买了一台机器用来生产空调,小帅发现自己的产品销量不错,于是他想加大生产力度,那可以通过什么方法来提高生产效率呢?

方案一:在这个工厂旁边再开一家工厂购买一台机器用来生产空调(多进程的解决方案)

方案二 :在原本的工厂内再购买一台机器用来生产空调(多线程的解决方案)

那么很显然第二种解决方案更划算,场地和空间都是复用之前的,共用一套资源。

1.线程和进程的关系:进程包含线程!

只有第一个线程启动的时候,开销是比较大的.后续线程就省事了个进程可以包含一个线程,也可以包含多个线程.(不能没有)。你线程1 new 的对象在线程2,3,4 里都可以直接使用。线程1 打开的文在线程2,3,4 里都可以直接使用。
同一个进程里的多个线程之间,共用了进程的同一份资源(主要指的是 内存 和 文件描述符表)。
注:操作系统,实际调度的时候是以线程为单位进行调度的.
如果每个进程有多个线程了,每个线程是独立在 CPU 上调度的。

线程是操作系统调度执行的基本单位,每个线程也都有自己的执行逻辑 (执行流)。

2.面试题:进程和线程之间的区别与联系。

1.进程包含线程! 一个进程里面可以有一个线程,也可以有多个线程。


2.进程线程都能解决并发编程问题场景.但是进程在频繁创建和销毁中,开销更高.线程开销更低,(线程比进程更轻量)。


3.进程是系统分配资源(内存,文件资源....) 的基本单位。线程是系统调度执行的基本单位(CPU)。


4进程之间是相互独立的各自有各自的虚拟地址空间,同一个进程内部的多个线程之间,共用同一个内存空间以及文件资源,一个进程挂了其他进程一般都没事。但是一个线程挂了,很可能把整个进程都带走!

三、第一个多线程程序

那么在Java中进行多线程编程的话如何实现呢?


在 Java 标准库中,就提供了一个 Thread 类,来表示/操作线程。
Thread 类也可以视为是 Java 标准库提供的 API。

即创建好的 Thread 实例,其实和操作系统中的线程是一一对应的关系。
操作系统,提供了一组关于线程的 API(C 语言风),Java 对于这组 API 进一步封装了一下,就成了 Thread 类。

(一)、Thread类的基本用法
写法一:继承自Thread,重写run()

那么通过Thread类创建线程有很多种方法,其中最简单的就是创建子类继承自Thread,重写run()方法。

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("hello Thread");
    }
}

注意,run()方法体中描述了这个线程内部要执行哪些代码。因为每个线程都是并发执行的.(各自执行各自的代码)因此就需要告知这个线程,你执行的代码是什么。
run()方法中的逻辑,是在新创建出来的线程中,被执行的代码,意思就是并不是我一定义这个类,一写 run 方法,线程就创建出来了,相当于领导已经把任务安排好了,我还没开始干呢!

public class demo1 {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
    }
}

需要调用这里的start()方法,才是真正在系统中创建了线程,才开始真正执行上面的run操作。

那么我们再写一个程序来仔细观察一下线程的执行情况,我们这里通过一个while循环来打印一个语句,通过sleep方法来控制打印的速度。

class MyThread2 extends Thread{
    @Override
    public void run() {
        while (true){
            System.out.println("hello thread!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class demo2 {
    public static void main(String[] args) {
        Thread t = new MyThread2();
        t.start();
 
        while (true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

那么我们知道,在一个进程中,至少会有一个线程。
在一个java 进程中,也是至少会有一个调用 main 方法的线程(这个线程不是你手动搞出来的)。
自己创建的 t 线程和 自动创建的 main 线程,就是并发执行的关系(宏观上看起来是同时执行)。
此处的"并发 = 并行+并发"宏观上是区分不了并行和并发的.都取决于系统内部的调度

我们可以发现现在两个线程,都是打印一条,就休眠个1s。
当 1s 时间到了之后,系统先唤醒谁呢?
通过运行结果看起来这个顺序不是完全确定(随机的)
每一轮,1s 时间到了之后,到底是先唤醒 main 还是 thread,这是随机的,对于操作系统来说,内部对于线程之间的调度顺序,在宏观上可以认为是随机的,即所谓的——抢占式执行!
那么对于这个随机性,会给多线程编程带来很多其他的麻烦!!

写法二:

创建一个类,实现Runnable接口,再创建Runnable实例传给Thread实例,通过Runnable来描述任务的内容。

class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("hello java");
    }
}
public class demo3 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}

写法三:匿名内部类

也就是上面两种写法的翻版,通过一个匿名内部类来实现:

public class demo4 {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("hello javaEE");
            }
        };
        t.start();
    }
}

* 通过匿名内部类来实现。
 * 创建一个匿名内部类,继承自Thread类。
 * 同时重写run方法。
 * 同时再new出这个匿名内部类的实例。

写法四:匿名内部类的方法2
* new 的 Runnable,针对这个创建的匿名内部类 同时new出的Runnable实例传给Thread的构造方法。
 * 通常认为这种写法好一点 能够做到让线程和线程执行的任务,更好的进行解耦。写代码追求高内聚,低耦合。
 * Runnable 单纯的只是描述了一个任务 至于这个任务是要通过一个进程来执行,还是线程池来执行 Runnable本身并不关心。
public class demo5 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello 多线程");
            }
        });
        t.start();
    }
}
写法五:Lambda(可以代替内部类的方式)

public class demo6 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
        System.out.println("hello Thread");
    });
        t.start();
    }
}

创建多线程的方式还有很多种,以上五种必须熟练掌握

标签:run,Thread,JavaEE,线程,进程,new,多线程,public
From: https://blog.csdn.net/weixin_72703349/article/details/142458567

相关文章

  • JavaEE——多线程Thread 类及常见方法
    目录 一、Thread(Stringname)二、是否后台线程isDeamon()三、是否存活isAlive()四、run()方法和start()方法的区别五、中断线程法一:法二:六、线程等待join()七、线程休眠sleep()一、Thread(Stringname)定义:这个东西是给线程(thread对象)起一个名字。起一个......
  • Java多线程
    文章目录前言1实现多线程1.1多线程概述1.2多线程的实现方式1.3线程休眠1.4线程优先级1.5守护线程2线程同步2.1同步代码块2.2Lock锁2.3死锁3生产者消费者3.1生产者和消费者模式概述3.2阻塞队列基本使用3.3阻塞队列实现等待唤醒机制前言"劝君莫惜金......
  • 万象更新 Html5 - h5: h5 通过 web worker 实现多线程
    源码https://github.com/webabcd/Html5作者webabcd万象更新Html5-h5:h5通过webworker实现多线程示例如下:h5\webWorker\worker.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>通过web......
  • 万象更新 Html5 - h5: h5 通过 web worker 实现多线程(演示如何转移数据的所有权)
    源码https://github.com/webabcd/Html5作者webabcd万象更新Html5-h5:h5通过webworker实现多线程(演示如何转移数据的所有权)示例如下:h5\webWorker\worker_transferable.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"&......
  • ARS展览项目(七)——C++多线程:Socket+表情识别整合
    说明一下我这边做表情识别和Socket,表情识别要实时,Socket要一直监听表情识别的结果,那么就只好用C++多线程来解决这个“两个功能一直并且同时运行”的问题。否则,如果是单线程的话,只能运行表情识别一段时间,切换发送一段时间,又切换回来,这样没有多线程好。还要说解决的难点写成多......
  • ARS展览项目(七)——C-多线程:Socket-表情识别整合
    说明一下我这边做表情识别和Socket,表情识别要实时,Socket要一直监听表情识别的结果,那么就只好用C++多线程来解决这个“两个功能一直并且同时运行”的问题。否则,如果是单线程的话,只能运行表情识别一段时间,切换发送一段时间,又切换回来,这样没有多线程好。还要说解决的难点写成多......
  • 28. 多线程、互斥锁
    1.多线程理论1.1什么是线程(1)概念在操作系统中,每个进程都有一个内存空间地址。而且默认每个进程都有一个控制线程,即自带一个主线程。进程是用来把资源集中到一起(进程是一个资源单位,或者称资源集合),线程是CPU上的执行单位。多线程(即多个控制线程)的概念:一个进程中存在多个控制......
  • 多线程之手撕生产者-消费者
    要点维护一个资源(在生产者-消费者中即流水线的位置)池,实现put()/get()两个函数。由于对信号量的操作是互斥的,要引入条件变量和信号量。实现资源池类Pool,成员变量:mtx:mutexcv:condition_variableque:queuecapacity:int实现资源池类Pool,成员函数:Tget():获取......
  • JAVA多线程
    一、并发和并行    并发:同一时刻,多个指令在单个CPU上交替执行。    并行:同一时刻,多个指令在多个CPU上同时执行。二、多线程的实现方式1.继承Thread类的方式进行实现。publicclassThreadDemo{publicstaticvoidmain(String[]args){MyT......
  • 多线程问题:异常处理,单例
    1)多线程异常处理多线程中如何捕获抛出异常到主线程a)catch中使用std::current_exception();获得正在处理的异常b)通过引用类型std::exception_ptr&_ex_ptr传出c)std::rethrow_exception(ex_ptr);重新抛出异常usingnamespacestd; try{ std::exception_ptrex_ptr;......