Java多线程简介

简介: Java多线程

Java.Thread(线)


image.png


image.png


image.png

1 进程和线程的概念以及他们直接的关系

前言:说起进程,就不得不说下程序,程序是指令和数据的有序集合,其本身没有任何允许的含义,是一个静态的概念

进程(process)

进程是执行程序的一个执行过程,它是一个动态的概念,是系统资源分配的单位

一个进程可以有多个线程,比如视频中看视频听声音看弹幕

通常在一个进程中包含若干个线程,当然一个进程中至少包含一个线程,不然没有存在的意义,线程是CPU调度和执行的单位

进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。

线程(thread)

Java中默认的线程有main(自己写的用户线程),gc(垃圾回收,是JVM给我们写的叫守护线程)

线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。

一个正在运行的软件(如迅雷)就是一个进程,一个进程可以同时运行多个任务( 迅雷软件可以同时下载多个文件,每个下载任务就是一个线程), 可以简单的认为进程是线程的集合。

进程与线程的关系

一个程序就是一个进程,而一个程序中的多个任务则被称为线程。进程是表示资源分配的基本单位,又是调度运行的基本单位。,亦即执行处理机调度的基本单位。 进程和线程的关系:

一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。

资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量,即每个线程都有自己的堆栈和局部变量。

处理机分给线程,即真正在处理机上运行的是线程。

线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

注意

很多多线程是模拟出来的,真正的多线程指的是有多个CPU,即多核,如服务器,如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的速度很快,所以就有同时执行的错局

2 start()方法和run()方法的区别

   start方法是启动线程,run方法只是去执行线程的代码

3 线程创建的3种方式

因为Java是单继承,所以推荐使用实现runnable接口,runnable可以避免单继承局限性,使用灵活方便,方便同一个对象被多个线程调用

1 继承Thread类(重点)

Thread源码也是实现Runable接口

1 继承Thread类

2 重写run方法,在run方法中编写线程执行代码

3 创建线程对象,调用它的start方法去启动线程

       4 总结: 线程开启不一定立刻执行,是由CPU调度安排,每次执行结果都不一样.他们是交替同时执行的


package com.wyh.thread;
/**
 * @program: Thread
 * @description: 多线程测试
 * @author: 魏一鹤
 * @createDate: 2021-12-23 23:37
 **/
//创建线程的方式1:继承Thread类 重写它的Run方法,调用start调用线程
public class TestThread1 extends Thread {
    @Override
public void run() {
//run方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("我是run方法 = " + i);
        }
    }
public static void main(String[] args){
//创建一个线程对象
        TestThread1 testThread1 = new TestThread1();
//调用它的start方法去开启线程
        //start方法才是开启线程  run方法知识去执行线程中的代码
        testThread1.start();
//testThread1.run();
        //main方法 主线程
        for (int i = 0; i < 2000; i++) {
            System.out.println("我是main方法 = " + i);
        }
    }
}


2 实现Runnable接口(重点)

1 实现runnable接口

2 实现run方法,编写线程代码

3 新创建线程对象,调用start方法去启动线程


package com.wyh.thread;
/**
 * @program: Thread
 * @description: 实现runnable接口
 * @author: 魏一鹤
 * @createDate: 2021-12-24 23:59
 **/
//创建线程方式2 实现runnable接口,重写run方法 ,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread2  implements  Runnable{
    @Override
public void run() {
//run方法线程体
        for (int i = 0; i < 100; i++) {
            System.out.println("我是run方法 = " + i);
        }
    }
public static void main(String[] args){
//创建runnable接口的实现类对象
        TestThread2 testThread2 = new TestThread2();
//创建线程,通过线程对象开启线程 代理
        Thread thread=new Thread(testThread2);
//调用start方法
        thread.start();
//也可以简写为以下格式
       // new Thread(testThread2).start();
        //main方法 主线程
        for (int i = 0; i < 2000; i++) {
            System.out.println("我是main方法 = " + i);
        }
    }
}


3 实现Callable接口(了解)

1 实现callable接口,需要返回值类型
2 重写call方法,需要抛出异常
3 创建目标对象
4 开启服务(创建执行服务)
5 提交执行
6 获取结果
7 关闭服务


///////////////////////////单个线程
package com.wyh.thread;
import java.util.concurrent.*;
/**
 * @program: Thread
 * @description: 实现callable接口
 * @author: 魏一鹤
 * @createDate: 2021-12-26 23:40
 **/
public class TestThread5 implements Callable<Object> {
//实现callable需要重写它的call方法
    @Override
public Object call() throws Exception {
for (int i = 0; i < 100; i++) {
            System.out.println("我在学习"+i);
        }
return null;
    }
public static void main(String[] args) throws Exception {
//线程体 实现类对象
        TestThread5 testThread5 = new TestThread5();
//创建执行服务                              创建线程池    需要几个线程就写几个
        ExecutorService executorService = Executors.newFixedThreadPool(1);
//提交执行
        Future<Object> submit = executorService.submit(testThread5);
//获取结果
        Object o = submit.get();
//打印返回结果
        System.out.println(o);
//关闭服务
        executorService.shutdown();
//主线程
        for (int i = 0; i < 1000; i++) {
            System.out.println("我在划水"+i);
        }
    }
}
///////////////////////////多个线程
package com.wyh.thread;
import java.util.concurrent.*;
/**
 * @program: Thread
 * @description: 实现callable接口
 * @author: 魏一鹤
 * @createDate: 2021-12-26 23:40
 **/
public class TestThread5 implements Callable<Object> {
//实现callable需要重写它的call方法
    @Override
public Object call() throws Exception {
for (int i = 0; i < 100; i++) {
            System.out.println("我在学习"+i);
        }
return null;
    }
public static void main(String[] args) throws Exception {
//线程体 实现类对象
        TestThread5 testThread1 = new TestThread5();
        TestThread5 testThread2 = new TestThread5();
        TestThread5 testThread3 = new TestThread5();
//创建执行服务                              创建线程池    需要几个线程就写几个
        ExecutorService executorService = Executors.newFixedThreadPool(3);
//提交执行
        Future<Object> submit1 = executorService.submit(testThread1);
        Future<Object> submit2 = executorService.submit(testThread2);
        Future<Object> submit3 = executorService.submit(testThread3);
//获取结果
        Object o1 = submit1.get();
        Object o2 = submit2.get();
        Object o3 = submit2.get();
//打印返回结果
        System.out.println(o1);
        System.out.println(o2);
        System.out.println(o3);
//关闭服务
        executorService.shutdown();
//主线程
        for (int i = 0; i < 1000; i++) {
            System.out.println("我在划水"+i);
        }
    }
}

实现callable接口的特点

优点
1 可以自定义返回值
2 可以抛出异常
缺点
1 代码稍微复杂一些
目录
相关文章
|
15天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
70 17
|
13天前
|
自然语言处理 Java 关系型数据库
Java mysql根据很长的富文本如何自动获取简介
通过使用Jsoup解析富文本并提取纯文本,然后根据需要生成简介,可以有效地处理和展示长文本内容。该方法简单高效,适用于各种应用场景。希望本文对您在Java中处理富文本并生成简介的需求提供实用的指导和帮助。
50 14
|
25天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
14天前
|
自然语言处理 Java 关系型数据库
Java mysql根据很长的富文本如何自动获取简介
通过使用Jsoup解析富文本并提取纯文本,然后根据需要生成简介,可以有效地处理和展示长文本内容。该方法简单高效,适用于各种应用场景。希望本文对您在Java中处理富文本并生成简介的需求提供实用的指导和帮助。
31 9
|
10天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
27天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
27天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
28天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
54 3
|
28天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
150 2
|
5月前
|
存储 监控 Java
Java多线程优化:提高线程池性能的技巧与实践
Java多线程优化:提高线程池性能的技巧与实践
151 1