Java13-多线程

news2025/1/23 17:39:42

一:基本概念:程序,进程,线程

程序: 是完成特定任务,用某种语言编写的一组指令集合,即指一段静态的代码

进程:是程序的一次执行过程,或是正在运行的一个程序。

线程:进程可以进一步细分为线程,是一个程序内部的一条执行路径。线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计算器,多个线程共享同一个进程中的结构:方法区和堆

二:线程的创建

方法一:继承类Thread,遍历100以内的偶数

public  class  MyThread extends Thread{
    @Override
    public void run() {
        for(int i=0;i<100;i++) {
            if (i % 2 == 0) {
                System.out.println(getName() + "--" + i);
            }
        }
    }

    public static void main(String []args){
        MyThread m1 =new MyThread();
       //启动线程,调用run()方法
        m1.start();
 
    }
}

方法二:实现Runnable接口,遍历100以内的偶数

public class RunnableTest implements  Runnable{

    @Override
    public void run() {
        for(int i=0;i<100;i++){
            if(i%2==0){
                System.out.println(Thread.currentThread().getName()+"-"+i);
            }
        }
    }

    public static void main(String[] args) {
        RunnableTest run = new  RunnableTest();
        Thread t1 =new Thread(run);

 //启动线程,调用run()方法
       t1.start();
   

    }
}

两种方式的比对:

开发中优选选择实现Runnable接口方式

原因: 1. 实现的方式没类的单继承局限性

             2.实现的方式更适合来处理多个线程共享数据的情况

联系:public class Thread implements Runnable

相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中

              目前两种方式,要想启动线程,都是调用Thread类的start()

三 :Thread类的常用方法:

1.start():启动当前线程,调用当前线程的run()

2.run():通常需要重写Threa类中的此方法,将创建线程要执行的操作声明在此方法中

3.currentThread(): 静态方法,返回执行当前代码的线程

4.getName():获取当前线程的名字

5.setName():设置当前线程的名字

6.yield():释放当前cpu的执行权

7.join():在线程a中调用线程b的join(),此时线程a进入阻塞状态,直到线程b完全执行完以后,线程a结束阻塞状态

8.sleep(long millitime):让当前线程睡眠,指定的millitime:毫秒,在指定的millitime时间,线程进入阻塞状态

9.isAlive():判断当前线程是否存活

四 :线程的生命周期:

新建:当一个Thread类或其子类的对象被声明和创建时,新生的线程对象处于新建状态

就绪:处于新建状态的线程被start()后,将进入线程队列等待cpu时间片,此时它已经具备的运行的条件,只是没分配到cpu资源

运行:当就续的线程被调度并获取得cpu资源时,便进入运行状态,run()方法定义了线程的操作和功能

阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出cpu并临时中止自己的执行,进入阻塞状态

死亡:线程完成了它的全部工作或线程被提前强制性地中止或出现异常导致结束

五 :线程的同步:

1)卖票,线程安全问题的引出:

public class Windows extends Thread{
    private  static int tickets=100;


    @Override
    public void run() {
        while (true) {


                if (tickets > 0) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票的票号为:" + tickets);
                    tickets--;

                } else {
                    break;
                }
            }

        }

    public static void  main(String[]args){
        Windows w1 =new Windows();
        Windows w2 =new Windows();
        Windows w3 =new Windows();
        w1.setName("窗口一:");
        w2.setName("窗口二:");
        w3.setName("窗口三:");
        w1.start();
        w2.start();
        w3.start();

    }
}

4执行结果:

窗口二:卖票的票号为:100
窗口一:卖票的票号为:100

窗口三:卖票的票号为:98
窗口三:卖票的票号为:97
窗口一:卖票的票号为:97

2)线程安全问题的解决:(继承类)同步代码块,关键字:synchronized

public class Windows extends Thread{
    private  static int tickets=100;


    @Override
    public void run() {
        while (true) {
            //同步监视器
            synchronized (Windows.class) {

                if (tickets > 0) {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票的票号为:" + tickets);
                    tickets--;

                } else {
                    break;
                }
            }

        }
    }

    public static void  main(String[]args){
        Windows w1 =new Windows();
        Windows w2 =new Windows();
        Windows w3 =new Windows();
        w1.setName("窗口一:");
        w2.setName("窗口二:");
        w3.setName("窗口三:");
        w1.start();
        w2.start();
        w3.start();

    }
}

3)线程安全问题的解决:(实现接口)同步代码块,关键字:synchronized

public class Windows2 implements Runnable {
    private int tickets=100;

    @Override
    public void run() {

        while (true) {
             //同步监视器
           synchronized (this) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + tickets);
                    tickets--;
                } else {
                    break;
                }
            }
        }
   }
    public static void main(String[] args) {
        Windows2 win =new   Windows2();
        Thread t1 =new Thread(win);
        Thread t2 =new Thread(win);
        Thread t3 =new Thread(win);
        t1.setName("窗口一:");
        t2.setName("窗口二:");
        t3.setName("窗口三:");
        t1.start();
        t2.start();
        t3.start();

    }
}

4)线程安全问题的解决:(继承类)同步方法,关键字:synchronized

public class SynchronizedTest1 extends Thread {
    private  static int tickets=100;
        @Override
        public void run() {
            while (true) {

                show();
                if(tickets<=0){
                    break;
                    }
                }

            }

private static synchronized  void show() {
    if (tickets > 0) {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "卖票的票号为:" + tickets);
        tickets--;

    }
}
        public static void  main(String[]args){
            SynchronizedTest1 w1 =new SynchronizedTest1();
            SynchronizedTest1 w2 =new SynchronizedTest1();
            SynchronizedTest1 w3 =new SynchronizedTest1();
            w1.setName("窗口一:");
            w2.setName("窗口二:");
            w3.setName("窗口三:");
            w1.start();
            w2.start();
            w3.start();

        }
    }

5)线程安全问题的解决:(实现接口)同步方法,关键字:synchronized

public class SynchronizedTest2 implements Runnable {

        private int tickets=100;

        @Override
        public void run() {
            while (true) {

                    show();
                   if(tickets<=0){
                        break;
                    }
                }
            }
         public synchronized void show(){
             if(tickets>0) {
                 try {
                     Thread.sleep(100);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 System.out.println(Thread.currentThread().getName() + tickets);
                 tickets--;

             }
         }
        public static void main(String[] args) {
            SynchronizedTest2 win =new SynchronizedTest2();
            Thread t1 =new Thread(win);
            Thread t2 =new Thread(win);
            Thread t3 =new Thread(win);
            t1.setName("窗口一:");
            t2.setName("窗口二:");
            t3.setName("窗口三:");
            t1.start();
            t2.start();
            t3.start();

        }




}

总结:

方式一:同步代码块

synchronized(同步监视器){

//需要被同步的代码

}

说明:

1.操作共享数据的代码,即为需要被同步的代码--不能包含代码多了,也不能包含代码少了。

2.共享数据:多个线程共同操作的变量。比如ticktet

3.同步监视器,俗称锁,任何一个类的对象,都可以充当锁, 要求:多个线程必须共用同一把锁

补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器

方式二:同步方法

如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的

注:

同步的方式,解决了线程的安全问题---好处

操作同步代码时,只能有一个线程参与,其他线程等待相当于是一个单线程的过程,效率低。

六 :线程的通信:

1.线程通信的主要方法:

wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器

notify():一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程被wait,就唤醒

优先级高的那个。

notifyAll():一旦执行此方法,就会唤醒所有被wait的线程

2.说明:

》wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中

》wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现IllegalMonitorStateException异常

》wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中

3.例题:线程交替打印数字:

public class CommunicationTest  {
    public static void main(String[] args) {
        Number number =new Number();
        Thread t1= new Thread(number);
        Thread t2= new Thread(number);
        t1.setName("线程一:");
        t2.setName("线程二:");
        t1.start();
        t2.start();

    }

}

class Number implements Runnable {
    private int num = 1;


    @Override
    public void run() {
        synchronized (this) {
            while (true) {
                notifyAll();

                if (num <= 100) {
                    System.out.println(Thread.currentThread().getName() + "打印的数字为:" + num);
                    num++;
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }


                } else {
                    break;
                }

            }
        }
    }
}

4.面试题: sleep()和wait()异同:

相同点:

一旦执行方法,都可以使当前的线程进入阻塞状态

不同点:

1)两个方法声明的位置不同,Thread类中声明sleep(),Object类中声明wait()

2)调用的要求不同:sleep()可以在任何需要的场景下调用,wait使用在同步代码块或同步方法中

3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁

七 :创建线程的另外两种方式:

方式一:实现Callable接口:

例题1: 实现打印100以内的偶数并求和:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;


public class CallableTest {
    public static void main(String[] args) {
        NumberTest number =new NumberTest();
        FutureTask futureTask = new FutureTask(number);
        new Thread(futureTask).start();
        Object obj = null;
        try {
            obj = futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(obj);


    }
}
class NumberTest implements Callable{

    @Override
    public Object call() throws Exception {
        int sum=0;
        for(int i=0;i<=100;i++){
            if(i%2==0){
                System.out.println(Thread.currentThread().getName()+"-"+i);
                sum+=i;
            }
        }
        return sum;


说明:如何理解实现Callable接口方式创建多线程比实现Runable接口创建方式强大?
》call() 可以返回值的
》call()可以抛出异常,被外面的操作捕获,获取异常的信息
》Callable是支持泛型的


  方式二:线程池:
例题1: 实现打印100以内的偶数并求和:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class NumberThread implements Runnable{

    @Override
    public void run() {
        for(int i=0;i<=100;i++){
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName()+"-"+i);
            }
            }
        }
    }

public class ThreadPool {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //启动线程
        executorService.execute(new NumberThread());
    }
}

使用线程池的好处:

》提高响应速度(减少创建新线程的时间)

》降低资源消耗(重复利用线程池中线程,不需要每次都创建)

》便于线程管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/413874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统之MobaXterm远程连接centos的GNOME桌面环境

Linux系统之MobaXterm远程连接centos的GNOME桌面环境一、MobaXterm介绍1.MobaXterm简介2.MobaXterm功能特点二、centos安装GNOME桌面1.本地环境介绍2.安装GNOME桌面环境3.本地进入Linux桌面三、MobaXterm远程连接centos1.打开MobaXterm软件2.远程连接本地Linux系统四、远程连接…

如何利用ChatGPT辅助优化刷题性能

根据土著刷题共建群里的一个小伙伴反馈&#xff0c;刷题会出现切题卡顿的情况&#xff0c;有时会出现滑不动的情况。 定位问题 为了定位切题卡顿问题的具体原因&#xff0c;测试了高低端手机&#x1f4f1;、切换2G、3G、4G低网络状态等各种影响切题的现实情况&#xff0c;经过借…

门店零售系统有哪些功能模块?能带来哪些帮助?

门店零售系统是一种用于管理门店销售、库存、采购等业务的软件系统&#xff0c;可以帮助门店提高管理效率、降低操作风险、优化运营决策&#xff0c;从而增强市场竞争力和顾客满意度。 一、门店零售系统的4大功能 1、商品管理 该模块主要用于管理门店的商品信息&#xff0c;包…

arcgis中地理配准之栅格平移

背景 前面写过一篇文章,是针对有两个对应的栅格数据进行配准的 Arcgis地理配准栅格数据 有时候需要没有对应的栅格数据,只有单幅栅格数据,而且知道平移参数,这时候可以通过平移参数来平移栅格,而且在unity中不能直接识别坐标值很大的数据,只能通过平移将坐标值减少,才…

【分布式事务AT模式 SpringCloud集成Seata框架】分布式事务框架Seata详细讲解

前言 上篇文章我们讲述了如何启动seata的本地服务&#xff0c;并且注册到nacos使用&#xff0c;这篇文章将在SpringCloud中整合Seata框架 上篇文章传送门&#xff1a;https://blog.csdn.net/Syals/article/details/130102851?spm1001.2014.3001.5501 本篇主要内容&#xff…

Docker几个概念

Docker几个概念&#xff0c;有不正确地方欢迎指正 一、首先来看一句话&#xff1a;没有Cgroups就没有LXC&#xff0c;没有LXC就没有Docker。 1、什么是Cgroup呢&#xff1f;Cgroup又名Control group&#xff0c;是Linux内核提供的一种可以限制、记录、隔离进程组所使用的物理…

VLAN 基础与划分及配置

我们都知道 VLAN 的中文名为"虚拟局域网"&#xff0c;VLAN 是一种将局域网设备从逻辑上划分成一个个不同的网段&#xff0c;从而实现虚拟工作组的新兴数据交换技术。这一新兴技术主要应用于交换机和路由器中&#xff0c;但主流应用还是在交换机之中。那今天咱们就和海…

Linux网络连接出现问题

报错截图 1.先查看NetworkManager是否启动 systemctl status NetworkManager如果输出结果中包含 "active (running)" 表示 NetworkManager 已经启动并正在运行 2.查看DNS是否配置 cat vim /etc/resolv.conf 1.查看是否有配置信息&#xff0c;如果没有请配置DNS …

华为ACL配置

模拟场景 服务器&#xff1a;192.168.3.100 销售部&#xff1a;192.168.1.1 开发部&#xff1a;192.168.2.1 模拟互联网&#xff1a;1.1.1.1 要求1&#xff1a;销售部不允许访问服务器 要求2&#xff1a;开发部可以访问服务器 要求3&#xff1a;互联网不可以访问服务器 拓扑图…

栈和队列经典题题解

目录 &#x1f349;一.括号匹配问题&#x1f349; &#x1f348;二.用队列实现栈&#x1f348; &#x1f34f;三.用栈实现队列&#x1f34f; &#x1f353;四.设计循环队列&#x1f353; &#x1f349;一.括号匹配问题&#x1f349; OJ链接力扣 题目描述&#xff1a; 思路&…

77-Linux_网络编程

网络编程一.主机字节序列和网络字节序列二.套接字地址结构1.通用socket地址结构2.专用的socket地址结构3.IP地址转换函数一.主机字节序列和网络字节序列 主机字节序列分为大端字节序和小端字节序&#xff0c;不同的主机采用的字节序列可能不同。 大端字节序是指一个整数的高位…

开店必备的5款超实用零售管理软件,第1个新手也能轻松使用!

现在越来越多的零售店老板都开始用零售管理软件来管理门店&#xff0c;提升效率&#xff0c;节约人力和时间成本。 但对于刚刚接触零售管理软件的老板来说&#xff0c;应用市场上的零售管理软件那么多&#xff0c;究竟哪些好用&#xff0c;哪些容易上手……还不太了解。 别着急…

CMake项目使用ctest+gtest进行单元测试

随着CMake工具越来越强大便捷&#xff0c;越来越多的C/C项目转而使用CMake来进行编译管理&#xff0c;它还提供了用于测试的ctest命令来执行项目中编写的单元测试。 本文就以一个实例来介绍如何使用ctest来进行单元测试。 一、环境准备 本文实例环境VSCodeMinGW64CMakegtest…

Qt程序CPU过高怎么定位解决?性能优化

自己开发的一个程序采用多线程调用url从网络上下载股票数据&#xff0c;一旦开启程序就特别的卡&#xff1b;想着优化一下&#xff1b;授之于鱼&#xff0c;不如 授之以渔&#xff1b; 1.CPU过高排查方法 &#xff08;1&#xff09;打开vs的性能探测器&#xff1b; &#xff…

Android端推送消息之极光推送

推送方式 轮询 --实现方式: 周期性主动获取网络中的数据; --缺点: 费电, 费流量; SMS --实现方式: 服务器端向手机端发送短信, 手机监听短信广播, 将拦截的短信信息进行显示; --优点: 省电, 省流量, 在没有网络的偏远地点也能接收到推送消息; --缺点: 费钱, 一毛钱一条;…

国产BI厂商:数字化时代的“卖水人”,扎根本土商业生态(上)

“没有数据&#xff0c;就没有竞争力。”随着中国经济以数字经济为重要引擎转向高质量发展道路&#xff0c;数据已成为推动经济增长的关键要素。Navesink顾问公司的创始人Thomas Redman认为&#xff0c;企业需要建立起对数据的组织和处理能力&#xff0c;只有这样才能收获大数据…

前端常用vscode插件

打开vscode配置 commandshiftP 选择Open User Setting&#xff08;首选项&#xff1a;打开用户设置(JSON)&#xff09; 1 Prettier - Code formatter "[javascript]": {"editor.defaultFormatter": "esbenp.prettier-vscode"},"[typescri…

日常记录:天梯赛练习集L1-043 阅览室

题目&#xff1a; 天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时&#xff0c;管理员输入书号并按下S键&#xff0c;程序开始计时&#xff1b;当读者还书时&#xff0c;管理员输入书号并按下E键&#xff0c;程序结束计时。书号为不超过1000的正整数。当管理员…

信安大佬真的用kali吗?

Kali只是现在网络安全和kali比较火的一个操作系统 下面我为大家讲讲kali系统都有那些优点 Kali介绍Kali Linux是基于Debian的Linux发行版&#xff0c; 设计用于数字取证操作系统。面向专业的渗透测试和安全审计。 集成化&#xff1a;预装超过300个渗透测试工具兼容好&#x…

【你听说了吗】GPT-5据说已经学完了世界上现存所有的视频

文章目录前言一、GPT-5会带来什么&#xff1f;二、我们该怎么办&#xff1f;总结前言 最近半年要说最火的产品&#xff0c;无疑是ChatGPT &#xff0c;很多同学都在用 GPT 帮助自己工作&#xff0c;学习&#xff0c;提高效率&#xff01;尤其是 GPT4&#xff0c;性能强 GPT3.5…