• Day62:java多线程


     概念:程序、进程、线程

    线程:是一个程序内部的一条执行路径(如果把进程比作河,那么线程就相当于河流的分支)
    cpu的核数:几核的cpu代表一个瞬时时间能处理任务数
    主频:任务之间的切换速度
    核数越多、主频越快越好

    多线程的创建和使用

    多线程:一个进程(一个程序运行时),可以分化为并行执行多个线程(多个子程序)

    何时需要多线程?
    1、程序需要同时执行两个或者多个任务
    2、需要一些后台运行的程序多线程的创建和启动,通过java.lang.Threat实现
    Thread类特性:
    run():每个线程通过某个特定的Thread对象的run()方法(它的主体叫做线程体,想要运行的代码逻辑写在这个方法里)来完成操作
    start():通过该Thread对象的start()方法(启动线程)来调用这个线程

    创建线程:
    方法一:继承Thread类实现多线程

    CC.java
    package jicheng;
    
    import java.lang.*;
    
    public class CC extends Thread {
    
        @Override
        public void run() {
            System.out.println("这里写的是多线程运行的代码");
            for (int i = 1; i <= 8; i++)
                System.out.println(i);
        }
    }

    B.java
    package jicheng;
    
    import java.lang.*;
    
    public class B {
        public static void main(String[] args) {
            //new实例的时候用其父类去接受即可(对象的多态)
            Thread t0 = new CC();  //继承Threat类的线程
            t0.start();//启动线程,运行run方法
    //        start执行好之后的main()方法的其他的代码与run方法的代码并行
            System.out.println("*****");
            //发现每次运行的结果不一样
            // 输出的和run方法输出混合,且顺序不一定,但是保持自己的输出顺序
            //这个就是多线程的异步,同步:代码严格按照从上到下执行
            //异步:开启线程之后run方法运行的和主程序的代码是并行执行的,没有先后关系
        }
    }
    方法二:实现Runnable接口实现多线程
    CC.java
    package jicheng;
    
    import java.lang.*;
    
    public class CC implements Runnable{//通过实现Runnable接口方式实现多线程
    
        @Override
        public void run() {
            System.out.println("这里写的是Runnable多线程运行的代码");
            for (int i = 1; i <= 8; i++)
                System.out.println(i);
        }
    }


    B.java
    package jicheng;
    
    import java.lang.*;
    
    public class B {
        public static void main(String[] args) {
            Thread t1 = new Thread(new CC());//传入Runnable实例
            t1.start();
            //或者可以这样写,多个线程可以这样子写
            // Thread t2 = new Thread(new CC(), "线程的名称");
        }
    }

    两种方法实现多线程的总结:

    • 接口:接口的方法都没有方法体,叫做实现run方法(一般用这个)

    • 继承:叫做重写run方法


    实现方法的好处:

    1. 避免单继承的局限性;(因为继承的话,如果父类是Thread就不能是其他的了,实现接口不影响去继承其他父类)

    2. 多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。

    多线程的优点:

    1. 提高应用程序的相应。对图形化界面更有意义,增强用户体验;

    2. 提高应用程序的CPU利用率;

    3. 改善程序结构(将长和复杂的进程分为多个线程,独立运行,利于理解和修改)。

    线程的生命周期

     

    线程的同步与死锁

    一个用户有3000元,需要实现支付宝和微信同时取出2000元

    package jicheng;
    
    import java.lang.*;
    
    public class B {
        public static void main(String[] args) {
            Acount a = new Acount();//定义账户对象
    
            //多线程对象
            User u_w = new User(a, 2000);//分别取出2000
            User u_z = new User(a, 2000);
    
            //微信和支付宝的线程
            Thread wechat = new Thread(u_w, "微信");//多线程对象和名称
            Thread pay = new Thread(u_z, "支付宝");
    
            wechat.start();
            pay.start();
    
        }
    }
    //多线程出现安全问题:
    //多线程调用这个方法会发现:线程共享资源的时候,一个线程在执行这个方法没有完毕时,另一个线程开始执行这个方法
    //出现问题:钱变成负数
    //解决:对于共享数据的操作,让一个线程执行完再让其他线程参与
    //通过synchronized同步锁来完成,在方法上加上该关键字即可
    //在普通方法上加同步锁,锁的是整个对象
    class Acount {
        public static int money = 3000;//账户原有3000元,全局变量
    
        public synchronized void drawing(int m) {
            String name = Thread.currentThread().getName();
            if (money < m) {
                System.out.println(name + "  余额不足");
            } else {
                System.out.println(name + "  原来:" + money);
                System.out.println(name + "  取走:" + m);
                money -= m;
                System.out.println(name + "  余额:" + money);
            }
        }
    }
    
    class User implements Runnable {
        Acount acount;
        int money;
    
        public User(Acount acount, int money) {
            this.acount = acount;
            this.money = money;
        }
    
        @Override
        public void run() {
            acount.drawing(money);
        }
    }
    View Code

    代码的注释看一下。

    在这个代码中,可以明白同步锁的作用,

    同步锁关键字:synchronized。

    这个代码不关键字,则:

    多线程出现安全问题:

    多线程调用drawing(取出钱)这个方法会发现:线程共享资源的时候,一个线程在执行这个方法没有完毕时,另一个线程开始执行这个方法

    出现问题:钱变成负数。

    解决:对于共享数据的操作,让一个线程执行完再让其他线程参与。

    通过synchronized同步锁来完成,在方法上加上该关键字即可。

    注意:在普通方法上加同步锁,锁的是整个对象,不是某一个方法,不同的对象就是不同的锁;静态的方法加synchronized,对于所有的对象都是同一个锁。

    除了上面代码内容,

    同步锁还可以这样写:

    synchronized(对象){
      //需要被同步的代码
    }

    如果针对对象要加同步锁,就加在方法上;

    针对某一段代码需要加同步锁,就在代码块上加上同步锁。

    不加同步锁关键字输出:

    加了同步锁关键字输出:

    线程的通信

    这三个方法只能用在有同步锁的方法或者代码块上



  • 相关阅读:
    java开发实战经典
    defer属性---->执行外部脚本
    深入理解JavaScript 模块模式
    JavaScript模块化开发一瞥
    缓存是新的内存
    php站点
    数据库
    .NET中使用Redis
    Scrum中的User Story
    如何编写敏捷开发中的user story
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12622333.html
Copyright © 2020-2023  润新知