首页 > 编程语言 >多线程(Java.Thread)学习(完结)

多线程(Java.Thread)学习(完结)

时间:2024-01-16 17:23:45浏览次数:30  
标签:love Java Thread int void 线程 new 多线程 public

多线程(Java.Thread)学习

线程简介:

1、线程是独立执行的路径
2、程序运行时有很多后台进程 比如主线程、young.gc、full.gc()
3、main是主线程,系统入口,用于执行整个程序
4、一个进程中、如果开辟多个线程,线程的运行由调度器安排调度、调度器的先后顺序不能人为干预
5、对同一份资源操作时,会存在资源抢夺问题,需要加入并发控制
6、线程会带来额外的开销,比如cpu调度时间,并发控制开销
7、每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

线程实现:

Thread

/**
 * @Description:TODO
 * @Author:Administrator
 * @Create 2024/1/12
 */
public class ThreadTest extends Thread{
    // 线程入口点
    @Override
    public void run() {
        // 线程体
        for (int i = 0;i<10;i++){
            System.out.println("我在看蒂法....."+i);
        }
    }
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
            threadTest.start();//开启线程,不一定立即执行 需要cpu调度
            threadTest.run();//立即执行线程 
        for (int i =0;i<10;i++){
            System.out.println("我在学Java Thread"+i);
        }
    }
}

开启 Thread 线程 下载网图,验证start方法线程执行交给cpu。

public class ThreadTest2 extends Thread {
    private String url;
    private String name;

    public ThreadTest2(String url,String name){
        this.url = url;
        this.name =name;
    }
    @Override
    public void run() {
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.download(url,name);
        System.out.println("下载了文件名为:"+name);
    }
    public static void main(String[] args) {
        ThreadTest2 threadTest1 = new ThreadTest2("https://aistyle.art/assets/files/2023-06-30/1688166112-995353-348703237-145251275241612-1956428239713994473-n.jpg","明日香1.jpg");
        ThreadTest2 threadTest2 = new ThreadTest2("https://bkimg.cdn.bcebos.com/pic/8b13632762d0f703918fecd9c0b1463d269759ee6f28?x-bce-process=image/format,f_auto/resize,m_lfit,limit_1,h_300","明日香2.jpg");
        ThreadTest2 threadTest3 = new ThreadTest2("https://aistyle.art/assets/files/2023-06-30/1688166112-995353-348703237-145251275241612-1956428239713994473-n.jpg","明日香3.jpg");

        threadTest1.start();
        threadTest2.start();
        threadTest3.start();
    }
}
class WebDownloader{
    //
    public void download(String url,String name){
        try{
            FileUtils.copyURLToFile(new URL(url),new File(name));
            System.out.println("下载完成");
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

实现runable接口

public class TestThread3 implements Runnable {
    public static void main(String[] args) {
        TestThread3 testThread3 = new TestThread3();
        new Thread(testThread3).run();

        for (int i = 0; i < 10; i++) {
            System.out.println("我在学习" + i);
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("我在聊天" + i);
        }
    }
}

初识并发问题

package org.example.redisson.JavaThread;

/**
 * @Description:TODO
 * @Author:Administrator
 * @Create 2024/1/12
 */

/**
 * 创建线程方式2:实现runable 接口重写run
 * 执行线程需要啊丢入new Thread(TestThread3)
 * 官方推荐 实现runable接口的方式
 */
public class TestThread4 implements Runnable {

    // 模拟票数
    private int ticketNums = 100;
    @Override
    public void run() {
        while (true){
            // 票剩余0时退出
            if (ticketNums <= 0){
                break;
            }
            // 模拟延时
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 对票数加锁
            synchronized ((Object)ticketNums){
                // 再次判断
                if (ticketNums <= 0){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNums--+"张票");
            }
        }
    }

    public static void main(String[] args) {
        TestThread4 ticket = new TestThread4();

        new Thread(ticket,"陈X华").start();
        new Thread(ticket,"席X辉").start();
        new Thread(ticket,"李X杰").start();
    }
}

龟兔赛跑

public class TestThread5 implements Runnable{
    private static String Winer;
    // 比赛内容
    public void run(){
        // 如果线程是兔子 让他休息20ms
        if(Thread.currentThread().getName().equals("兔子")){
            try{
                Thread.sleep(20);
            }catch(RuntimeException | InterruptedException e){
                e.printStackTrace();
            }
        }
        for(int i = 1;i<= 10;i++){
            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
            // 判断比赛是否结束
            Boolean flage = gameOver(i);
            if (flage){
                break;
            }
        }
    }

    public static void main(String[] args){
        TestThread5 testThread5 = new TestThread5();
        new Thread(testThread5,"兔子").start();
        new Thread(testThread5,"乌龟").start();
    }
    public Boolean gameOver(int step){
        // 胜利者诞生 停止比赛
        if(Winer != null){
            return true;
        }
        // 跑过了10 步 停止比赛
        if(step == 10){
            Winer = Thread.currentThread().getName();
            System.out.println("胜利者是"+Winer);
            return true;
        }
        return false;
    }
}

callable

函数式接口 lambda

JDK8 之前的写法


 public class TestLambda2{
// 一个接口只有一个实现方法:叫做函数式接口
interface ILove{
        void love(int a);
    }

public static void main(String[] args){
       ILove i = new I();
       i.love(521);
    }

 class I implements ILove{
        @Override
    public void love(int a){
            System.out.println("i love you " + a);
        }
    }
 } 

简化1:使用静态内部类

# 使用静态内部类

public class TestLambda2{
// 一个接口只有一个实现方法:叫做函数式接口
interface ILove{
        void love(int a);
    }

public static void main(String[] args){
       ILove i = new I();
       i.love(521);

    }
static class I implements ILove{
        @Override
    public void love(int a){
            System.out.println("i love you " + a);
        }
    }
 } 

简化2:局部内部类

public class TestLambda2{
// 一个接口只有一个实现方法:叫做函数式接口
interface ILove{
        void love(int a);
    }

public static void main(String[] args){
    class I implements ILove{
    @Override
    public void love(int a){
            System.out.println("i love you " + a);
        }
    }
       ILove i = new I();
       i.love(521);

    }
 } 

简化3:匿名内部类(通过new 构建 没有方法名)

interface ILove{
        void love(int a);
    }

public class TestLambda2{
// 一个接口只有一个实现方法:叫做函数式接口

public static void main(String[] args){
    ILove  i = new ILove(){
        @Override
        public void love(int a){
            System.out.print("i love you " + a)
        }
    };
        i.love(521);
    }
 } 

最终lambda版本

interface ILove {
    void love(int a,int b);
}
public class TestLambda2 {
    // 一个接口只有一个实现方法:叫做函数式接口
    public static void main(String[] args) {
        ILove i = (a,b) -> {
                System.out.println("i love you " + a+b);
        };
        i.love(520,521);
    }
}
Lambda总结

1、接口中只能有一个方法;
2、lambda执行业务逻辑时 必须带{},除非业务逻辑只有一行
3、多个参数 也可以去掉参数类型(全部去掉)

线程状态:

创建 new Thread()

就绪(等待cpu调度) start();

阻塞(阻塞结束后 等待cpu调度) sleep()、wait()或同步锁

sleep
sleep(ms) 指定当前线程阻塞的毫秒数;
sleep 存在异常InterruptedException;
sleep 时间到达后线程进入就绪状态;
sleep 可以模拟网络延时。倒计时等
每一个对象都有一把锁。sleep不会释放锁;
/**
 * @Description: 联系sleep 倒计时
 * @Author:Administrator
 * @Create 2024/1/13
 */

public class TestThreadSleep{
    public static void main(String[] args) throws InterruptedException {
        tenShutDown();
    }

    static void tenShutDown() throws InterruptedException {
        int num = 10;
        while (true){
            Thread.sleep(1000);
            System.out.println( num-- );
            if (num <= 0){
                break;
            }
        }

    }
}

join 使线程阻塞,相等于vip先执行
/**
 * @Description:测试 join,会使线程阻塞
 * @Author:Administrator
 * @Create 2024/1/13
 */

public class TestThreadJoin implements Runnable{

    @Override
    public void run() {
        for (int i = 1; i < 101; i++) {
            System.out.println("vip来了 统统闪开~ !"+i);
        }
    }
    public static void main(String[] args) throws InterruptedException {
        TestThreadJoin testThreadJoin = new TestThreadJoin();
        Thread thread = new Thread(testThreadJoin);
        thread.start();
        
        for (int i = 1; i < 101; i++) {
            System.out.println("main"+ i);
            if(i == 10){
                thread.join();// 强制执行 run方法 线程
            }
        }
    }
}

运行

start()、run()

销毁

不建议用stop、die废弃或官方不推荐的方法
  • 推荐基数的方式 停止线程
/*
 * @Description:不建议用stop、die废弃或官方不推荐的方法
 * 推荐基数的方式 停止线程
 * @Author:Administrator
 * @Create 2024/1/13
 */
public class TestThreadStop implements Runnable {
    public Boolean flag = true;
    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("走了" + i++ + "步数");
        }
    }

    // 设置一个公开的停止方法
    public void stop() {
        this.flag = false;
    }

    public static void main(String[] args) {
        TestThreadStop testThreadStop = new TestThreadStop();

        new Thread(testThreadStop).start();

        for (int i = 0; i < 100; i++) {
            System.out.println("main"+ i);
            if (i == 90) {
                // 循环90次的时候 停止线程
                testThreadStop.stop();
                System.out.println("线程该停止了");
            }
        }
    }

}

观察线程的状态

启动前:new
启动后:runnable
运行:Timed-waiting
结束: TERMINATED

线程的优先级

优先级:1-10;数字越大优先级越高;

守护线程

1、通过Thread.seDeamon(true) 设置
2、在线程start 前设置
3、用户线程挂掉,守护线程也会等待cpu调度挂掉

线程同步机制

多个线程同时对公共对象操作,就是并发问题
如何解决并发安全问题
1、使用线程同步队
sync 同步锁:
一个线程持有锁 会导致其他所有需要次锁的线程挂起
一定会损失性能
优先级高的线程,等待优先级低的线程 释放锁会有性能问题 鱼和熊掌不可兼得

三大不安全案例

1、两人同时对同一张银行卡取钱(超取问题)
2、网上买票(超卖问题)
3、1000个线程对ArrayList同时操作,数据不一致(array.add方法是根据下标位置,多个线程可能会同时锁定下标位置)

同步方法及同步块

sync

CopyOnWriteArrayList

JUC Java并发编程
java util.concurren.copyOnWirteArrayList;线程安全的数据类型

死锁

a 想占用 b的资源
b 想占用 a的资源 
都在等对方释放

Lock锁

ReentrantLock实现了Lock 是可重入锁
copyOnWirteArrayList 中使用了;
Sync和Lock的区别
Lock是显式锁 需要手动开启、关闭,sync是隐式锁 出了区域自动释放
Lock只有代码块锁,sync有代码块锁也有方法锁
使用Lock锁,JVM将花费较少的时间来调度线程,性能更好

生产者消费问题(线程协作)

生产者消费者问题
假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取出消费
如果仓库中没有产品,则生产者将产品放入仓库,否则停止并等待并等待仓库中的产品被消费者取走为止
如果仓库中放有产品,则消费者可以将产品取走消费,否则停止生产并等待,直到仓库中再次放入产品为止

管程法

信号灯法

设置flag信号灯管理 生产消费的通信 flag为true消费,否则生产

线程池

Executor

总结

标签:love,Java,Thread,int,void,线程,new,多线程,public
From: https://www.cnblogs.com/czh4869/p/17968124

相关文章

  • javascript node.js , java jvm , jdk, jre 的理解。
    网上的截图: 来看看node.js     再来看看java.     ......
  • MFC---多线程(线程死锁)
    死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。#include<stdio.h>#include<windows.h>#include<process.h>intiTickets=5000;CRITICAL_SECTIONg_csA;CRITICAL_SECTIONg_csB;//A窗口B窗口DWORDWINAPISellT......
  • MFC---多线程(线程同步之信号量)
    内核对象的状态触发状态(有信号状态),表示有可用资源。未触发状态(无信号状态),表示没有可用资源工作原理以一个停车场是运作为例。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来......
  • MFC---多线程(各种线程同步的比较总结)
    windows线程同步的方式主要有四种:互斥对象Mutex、事件对象event和关键代码段criticalSection,信号量对于上面介绍的三种线程同步的方式,它们之间的区别如下所述:●互斥对象和事件以及信号量都属于内核对象,利用内核对象进行线程同步时,速度较慢,但利用互斥对象和事件对象这样的内核对......
  • MFC---多线程(qq群聊的服务端和客户端)
    服务端//多线程+socket编程的一个联合使用//用互斥体进行线程同步socket编程临界区全局变量#include<WinSock2.h>#include<iostream>#include<windows.h>#include<process.h>#pragmacomment(lib,"ws2_32.lib")#defineMAX_CLNT256#defineMAX_BUF_S......
  • MFC---多线程(基本概念和线程同步之互斥对象)
    基本概念引入一个题目:Bingo老师提了一个需求:打印每隔3秒叫martin老师做一次俯卧撑持续20次每隔1秒钟叫rock老师甩头发持续50次每隔2秒钟叫西西老师唱歌持续40次线程(CPU调度和分派的基本单位)线程是在进程中产生的一个执行单元,是CPU调度和分配的最小单元,其在同一个进程中与......
  • MFC---多线程(线程同步之关键代码段)
    关键代码段,也称为临界区,工作在用户方式下。它是指一个小代码段,在代码能够执行前,它必须独占对某些资源的访问权。通常把多线程中访问同一种资源的那部分代码当做关键代码段。1.初始化关键代码段调用InitializeCriticalSection函数初始化一个关键代码段。InitializeCriticalSection(......
  • java调用jmeter集群服务压力测试 jmeter数据库压测
    目录〇、前言。一、jmeter工具安装。二、数据库驱动插件jar包安装。三、脚本开发与调试。四、加压设置。五、数据监听。  正文〇、前言。依据云栖大会项目部分数据库压测经验编写。一、jmeter工具安装。1、Apache官网下载地址:https://jmeter.apache.org/download_j......
  • logstash4j-用于日志的输入、转换处理、输出, java 开发者自己的 logstash
    项目简介logstash4j用于日志的输入、转换处理、输出,java开发者自己的logstash特性inputoutputfiltermetric开源地址logstash4j快速开始需要jdk1.8+maven3.x+maven引入<dependency><groupId>com.github.houbb</groupId><artifactId>logst......
  • Java 将所有的数据信息查询出来 ,进行映射
    查询出所有组织结构的数据,列表显示时进行映射 该代码查询的参数是逗号相隔的多个数据//查询对应组织机构List<Map<String,Object>>deptList=businessManagerMapper.querySysDept();Map<Object,List<Map<String,Object>>>groupMap=deptList.stream().co......