首页 > 编程语言 >JAVA多线程快速入门

JAVA多线程快速入门

时间:2024-07-04 12:26:40浏览次数:9  
标签:JAVA 入门 Thread void static 线程 new 多线程 public

  • 什么是多线程
    • 概述
      • 线程
        • 线程是操作系统能够进行运算调度的最小单位 它被包含在进程之中,是进程中的实际运作单位
        • 简单理解
          • 应用软件中互相独立,可以同时运行的功能
      • 进程
        • 进程是程序的基本执行实体/系统分配资源的基本单位
    • 作用
      • 充分利用cpu 提高效率
    • 应用场景
      • 软件中的耗时操作
        • 拷贝\迁移大文件
        • 加载大量的资源文件
      • 所有聊天软件/所有后台服务器/多个事情同时运行就需要用到多线程
  • 02 并发和并行
    • 并发
      • 概述
        • 在同一时刻,有多个指令在单个cpu上交替执行
    • 并行
      • 概述
        • 在同一时刻,有多个指令在多个cpu上交替执行

  • 03 多线程的实现方式
    • 1.继承Thread类的方式进行实现
    • 2 . 实现Runnable接口的方式进行实现
    • 3 . 利用Callable接口和Future接口方式实现
  • 继承Thread类的方式代码实现
  • public class MyThread extends Thread{
        //程序内容
        @Override
        public void run(){
            for (int i = 0;i<100;i++){
                System.out.println(getName()+"HelloWord");
            }
        }
    }
    
    public class ThreadDemo {
        public static void main(String[] args) {
            /*多线程第一种启动方式
            1.自己定义一个类继承Thread类
            2.重写run方法
            3.创建子类的对象,启动线程
             */
            MyThread t1 = new MyThread();
            MyThread t2 = new MyThread();
            t1.setName("线程一");
            t2.setName("线程二");
            //开启线程
            t1.start();
            t2.start();
        }
    }

    实现Runnable接口的方式代码实现

  • public class MyRun implements Runnable{
        @Override
        public void run() {
            for (int i=0;i<100;i++){
               /* Thread t = Thread.currentThread();
                System.out.println(t.getName()+"HelloWord");*/
                System.out.println(Thread.currentThread().getName()+"HelloWord!!!");
            }
        }
    }
    public class ThreadDemo {
        public static void main(String[] args) {
            /*
            多线程第二种启动方式
            1.自己定义一个类实现Runnable接口
            2.重写run方法,将此线程要执行的操作声明在run方法中
            3.创建Runnable接口的实现类对象
            4.将此Runnable接口的实现类对象作为参数传递到Thread类的构造器中,创建Thread类的对象,开启线程*/
    
          //创建runnable接口的实现类对象
            MyRun mr = new MyRun();
            //创建Thread类的对象
            Thread t1= new Thread(mr);
            Thread t2 = new Thread(mr);
            //线程赋值
            t1.setName("线程一");
            t2.setName("线程二");
            //启动
            t1.start();
            t2.start();
        }
    }

    利用Callable接口和Future接口方式代码实现

  • public class MyCallable implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            //  1到100之间的和
            int sum = 0;
            for (int i=1;i<=100;i++){
                sum +=i;
            }
            return sum;
        }
    }

测试类 

public class ThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*多线程的第三种实现方式
        特点:可以获取到多线程运行的结果

        1.  创建一个类Callable实现callable接口
        2.  重写call方法(有返回值,表示多线程运行的结果)
        3.  创建MyCallable对象(表示多线程要执行的任务)
        4.  创建FutureTask的对象(表示对Callable对象包装,可以获取到Callable对象执行后的结果)
        5.  创建Thread对象,构造方法中传入FutureTask对象  (开始线程)
        * */
        
        //创建MyCallable对象
        MyCallable mc = new MyCallable();
        //创建FutureTask对象
        FutureTask<Integer> ft = new FutureTask<>(mc);
        //创建Thread对象
        Thread t =new Thread(ft);
        //开启线程
        t.start();
        //获取线程运行结果
        Integer integer = ft.get();
        System.out.println(integer);
    }
}

 


  • 04 常见的成员方法
    • string  getName()                  返回此线程的名称
      void   setName(String name)        设置此线程的名称(构造方法也可以设置名字)
      static Thread currentThread()      获取当前正在执行的线程对象
      static void sleep(long time)       rang线程休眠,单位毫秒
      代码实现
    • public class MyThread extends Thread{
          public MyThread(String name) {
              super(name);
          }
          @Override
          public void run(){
              for (int i =0;i<100;i++){
                  try {
                      Thread.sleep(1000);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
                  System.out.println(getName()+"@"+"HelloWord!!!");
              }
          }
      }

      测试类

    • public class ThreadDemo {
          public static void main(String[] args) throws InterruptedException {
              /*
                  string  getName()                           返回此线程的名称
                  void   setName(String name)        设置此线程的名称(构造方法也可以设置名字)
              细节:
                  1.线程名字默认是Thread-X(x是序号,从0开始)
                  2.如果要设置线程名字,可以在创建线程对象时,调用setName()方法,也可以用构造方法设置
      
                  static Thread currentThread()  获取当前正在执行的线程对象
                      细节:
                              当JVM虚拟机启动之后,会自动的启动多条线程
                              其中有一条叫main线程
                              它的作用是调用main方法,并执行main方法中的代码
                              在以前我们所写的代码,都是在main方法中执行的
      
      
                  static void sleep(long time)       rang线程休眠,单位毫秒
                      细节:
                                  1.那条线程执行到这个方法,就停留对应时间
                                  2.时间到期之后,线程继续执行下面代码
                                       */
      
              MyThread t1 = new MyThread("线程一");
              MyThread t2 = new MyThread("线程二");
              //启动线程
              t1.start();
              t2.start();
      
              //Thread t = Thread.currentThread();
              //System.out.println(t.getName());  main
      
              /*System.out.println("线程一");
               Thread.sleep(1000);
              System.out.println("线程二");*/
          }
      }
      setPriority(int newPriority)        设置线程优先级
      final int getPriority()             获取线程的优先级
      代码实现
    • public class MyRunnable implements Runnable{
          @Override
          public void run() {
              for (int i = 0; i < 100; i++) {
                  System.out.println(Thread.currentThread().getName()+"~~~~~~"+i);
              }
          }
      }

      测试类

      • public class ThreadDemo {
            public static void main(String[] args) {
              /*setPriority(int newPriority)        设置线程优先级
                final int getPriority()                   获取线程的优先级
                */
                MyRunnable mr =new MyRunnable();
                Thread t1 = new Thread(mr,"线程一");
                Thread t2 = new Thread(mr,"线程二");
        
                t1.setPriority(1);
                t2.setPriority(Thread.MAX_PRIORITY);
                t1.start();
                t2.start();
        //        System.out.println(Thread.currentThread().getPriority());
            }
        }
         final void setDaemon(boolean on)    设置守护线程
         boolean isDaemon()                  判断是否为守护线程
        代码实现
      • 类一
      • public class MyThread1 extends Thread{
            @Override
            public void run(){
                for (int i = 0 ;i<10;i++){
                    System.out.println(Thread.currentThread().getName() + "~~~" + i);
                }
            }
        }

        类二

      • public class MyThread2 extends Thread{
            @Override
            public void run(){
                for (int i = 0 ;i<100;i++){
                    System.out.println(Thread.currentThread().getName() + "~~~" + i);
                }
            }
        }

        测试类

        public class ThreadDemo {
            public static void main(String[] args) {
                /*  final void setDaemon(boolean on)    设置守护线程
                    boolean isDaemon()    判断是否为守护线程
                    守护线程:当进程中的所有线程都是守护线程时,进程结束
                */
                // 创建线程对象
                MyThread1 t1 = new MyThread1();
                MyThread2 t2 = new MyThread2();
                // 设置线程名称
                t1.setName("女神");
                t2.setName("备胎");
                // 设置备胎线程为守护线程
                t2.setDaemon(true);
                //开启
                t1.start();
                t2.start();
            }
        }
        public static void yield()       礼让线程/出让线程
        代码实现
      • public class MyThread extends Thread{
            @Override
            public void run(){
                for (int i = 0; i < 100; i++) {
                    System.out.println(getName()+"~"+i);
                    Thread.yield();
                }
            }
        }

        测试类

      • public class ThreadDemo {
            public static void main(String[] args) {
                // public static void yield()       礼让线程/出让线程
                MyThread myThread1 = new MyThread();
                MyThread myThread2=new MyThread();
                // 设置线程名称
                myThread1.setName("线程一");
                myThread2.setName("线程二");
                //开启线程
                myThread1.start();
                myThread2.start();
            }
        }
         public final void join()   插入线程/线程插队
         代码实现
      • public class MyThread extends Thread{
            @Override
            public void run(){
                for (int i = 0; i < 100; i++) {
                    System.out.println(getName()+"#"+i);
                }
            }
        }

        测试类

      • public class ThreadDemo {
            public static void main(String[] args) throws InterruptedException {
                // public final void join()   插入线程/线程插队
                MyThread t1 =new MyThread();
                //设置名字
                t1.setName("鸣人");
                //开始线程
                t1.start();
                //插入线程
                t1.join();
        
                for (int i = 0; i < 10; i++){
                    System.out.println("main");
                }
            }
        }
        

    • 抢占式调度
      • 默认5
    • 非抢占调度

 


  • 05 线程的生命周期
  • JVM没有运行状态,当线程抢夺到CPU的执行权,JVM会把当前线程交给操作系统管理
  • 这里只是便于理解

  • 06 线程安全的问题
    • 同步代码块
      • 把操作共享数据的代码锁起来
      • 格式
        • synchronized(锁){
        • 操作共享数据的代码
        • }
      • 特点
        • 锁默认打开,有一个线程进去了,锁自动关闭
        • 里面的代码全部执行完毕,线程出来
      • 小细节
        • 锁是唯一的
          • 如果产生两个锁,两个线程分别进不同的锁,锁就无意义了
        • synchronized不能写在循环的外面,会导致抢到cpu执行权的线程独立执行完循环后,其他线程才会进入
        • 可以用当前类的class
    • 关于锁的代码实现
    • //同步代码块
      public class MyThread extends Thread {
          static int ticket = 0;
      
          //锁对象  一定是唯一的  加static就行
      //  static    Object boj = new Object();
          @Override
          public void run() {
              while (true) {
                  //同步代码块
                  synchronized (MyThread.class) {
                      if (ticket < 100) {
                          try {
                              Thread.sleep(10);
                          } catch (InterruptedException e) {
                              throw new RuntimeException(e);
                          }
                          ticket++;
                          System.out.println(getName() + "卖票:" + ticket);
                      } else {
                          break;
                      }
                  }
              }
          }
      }

      测试类

    • public class ThreadDemo {
          public static void main(String[] args) throws ExecutionException, InterruptedException {
              //创建对象
              MyThread t1 = new MyThread();
              MyThread t2 = new MyThread();
              MyThread t3 = new MyThread();
              t1.setName("窗口一");
              t2.setName("窗口二");
              t3.setName("窗口三");
      
              t1.start();
              t2.start();
              t3.start();
          }
      }

    • 同步方法
      • wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw== 编辑
    • 同步方法代码实现
    • //抽取方法
      public class MyRun implements Runnable{
          int ticket =0;
          @Override
          public void run() {
              //循环
              while (true){
                  //同步代码块
                    if (method()) break;
                }
              }
          private synchronized boolean method() {
              //判断共享数据是否到了末尾,如果到了末尾
              if (ticket==100){
                  return true;
              }else {
                  //没到末尾,卖票
                  try {
                      Thread.sleep(10);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
                  ticket++;
                  System.out.println(Thread.currentThread().getName()+"卖票:"+ticket);
              }
              return false;
          }
      }

      测试类

    • public class ThreadDemo {
          public static void main(String[] args) {
              MyRun mr = new MyRun();
      
              Thread t1 = new Thread(mr,"窗口一");
              Thread t2 = new Thread(mr,"窗口二");
              Thread t3 = new Thread(mr,"窗口三");
      
              t1.start();
              t2.start();
              t3.start();
          }
      }

    • Lock锁

  • 手动开关锁代码实现
  • //手动开锁 关锁
    public class MyThread extends Thread {
        static int ticket = 0;
        static Lock lock = new ReentrantLock();
    
        @Override
        public void run() {
            while (true) {
                //同步代码块
                //synchronized (MyThread.class) {
                lock.lock();
                try {
                    if (ticket < 100) {
                        Thread.sleep(10);
                        ticket++;
                        System.out.println(getName() + "卖票:" + ticket);
                    } else {
                        break;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    测试类

  • public class ThreadDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            //创建对象
            com.mtq.threadsafe01.MyThread t1 = new com.mtq.threadsafe01.MyThread();
            com.mtq.threadsafe01.MyThread t2 = new com.mtq.threadsafe01.MyThread();
            com.mtq.threadsafe01.MyThread t3 = new MyThread();
            //赋值
            t1.setName("窗口一");
            t2.setName("窗口二");
            t3.setName("窗口三");
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    

  • 07 死锁(只需理解即可,这是个错误)
  • 代码实现
  • public class MyThread extends Thread{
        static Object objA = new Object();
        static Object objB = new Object();
        @Override
        public void run(){
            //循环
            while (true){
                if ("线程A".equals(getName())){
                    synchronized (objA){
                        System.out.println("线程A获取到了objA的锁,准备拿objB锁");
                        synchronized (objB){
                            System.out.println("线程A获取到了objB的锁,顺利执行完一轮");
                        }
                    }
                }else if("线程B".equals(getName())){
                    if ("线程B".equals(getName())){
                        synchronized (objB){
                            System.out.println("线程B拿到了B锁,准备拿A锁");
                            synchronized (objA){
                                System.out.println("线程B拿到了A锁,顺利执行完一轮");
                            }
                        }
                    }
                }
            }
        }
    }
    

    测试类

  • public class ThreadDemo {
        public static void main(String[] args) {
            /*死锁*/
            MyThread t1 = new MyThread();
            MyThread t2 = new MyThread();
            t1.setName("线程A");
            t2.setName("线程B");
            t1.start();
            t2.start();
        }
    }
    

    输出结果

  • 会陷入一直不停止的状态

 


  • 08 生产者和消费者
    • 等待唤醒机制
      • 常见方法
    • 代码实现
    • 生产者类
    • public class Cook extends Thread {
          /*循环
            同步代码块
            判断共享数据是否到了末尾(到了末尾)
            判断共享数据是否到了末尾(没有到末尾,执行核心逻辑)*/
          @Override
          public void run() {
              while (true) {
                  synchronized (Desk.lock) {
                      if (Desk.count == 0) {
                          break;
                      } else {
                          //判断是否有食物
                          if (Desk.foodFlag == 1) {
                              try {
                                  //有:等待
                                  Desk.lock.wait();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          } else {
                              //没有:制作
                              System.out.println(getName() + "制作了一个巨无霸十层汉堡王");
                              //把制作好的放于桌子
                              Desk.foodFlag = 1;
                              //唤醒消费者
                              Desk.lock.notifyAll();
                          }
                      }
                  }
              }
          }
      }
      

      消费者类

    • public class Foodie extends Thread {
          /*循环
          同步代码块
          判断共享数据是否到了末尾(到了末尾)
          判断共享数据是否到了末尾(没有到末尾,执行核心逻辑)*/
      
          @Override
          public void run() {
              while (true) {
                  synchronized (Desk.lock) {
                      if (Desk.count == 0) {
                          break;
                      } else {
                          //判断是否有食物
                          if (Desk.foodFlag == 0) {
                              //没有继续等待
                              try {
                                  Desk.lock.wait();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          } else {
                              //每吃一份  -1
                              Desk.count--;
                              //有则吃
                              System.out.println("消费者" + getName() + "还能再吃" + Desk.count + "个巨无霸十层汉堡王");
                              //唤醒生产者
                              Desk.lock.notifyAll();
                              //桌子状态归为初始状态
                              Desk.foodFlag = 0;
                          }
                      }
                  }
              }
          }
      }

      共享数据类

    • public class Desk {
          /*作用:控制生产者和消费者的执行*/
      
          //是否有食物 0:没有食物  1:有食物
          public static int foodFlag = 0;
      
          //总个数
          public static int count = 10;
      
          //锁对象
          public static Object lock = new Object();
      }

      测试类

    • public class TreadDemo {
          public static void main(String[] args) {
              /*完成生产者和消费者(等待唤醒机制)的代码
              实现线程协作*/
              
              //创建线程的对象
              Cook c = new Cook();
              Foodie f = new Foodie();
      
              //赋值
              c.setName("肯德基");
              f.setName("疯狂的河马吃客");
              //启动
              c.start();
              f.start();
          }
      }

      运行结果

    • 等待唤醒机制(阻塞队列方式实现)
      • 阻塞队列的继承结构
  • 代码实现
  • 生产者类
  • public class Cook extends Thread {
        //阻塞队列
        ArrayBlockingQueue<String> queue;
    
        //构造方法
        public Cook(ArrayBlockingQueue<String> queue) {
            this.queue = queue;
        }
    
        @Override
        public void run() {
            while (true) {
                //不断的把食物放到阻塞队列中
                try {
                    queue.put("一个汉堡");
                    System.out.println("肯德基制作了一个汉堡");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    消费者类

  • public class Foodie extends Thread {
        //阻塞队列
        ArrayBlockingQueue<String> queue;
    
        //构造方法
        public Foodie(ArrayBlockingQueue<String> queue) {this.queue = queue;}
    
        @Override
        public void run() {
            while (true) {
                //不断从阻塞队列获取食物
                try {
                    String food = queue.take();
                    System.out.println("吃货正在吃" + food);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    测试类

  • public class ThreadDemo {
        public static void main(String[] args) {
            /*
             * 需求:利用阻塞队列完成生产者和消费者(等待唤醒机制)的代码
             * 细节
             *           生产者和消费者必须使用同一个阻塞队列*/
    
            //1.创建阻塞队列的对象
            ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(1);
    
            //创建线程对象,把阻塞队列传递过去
            Cook cook = new Cook(queue);
            Foodie foodie = new Foodie(queue);
    
            //开启
            cook.start();
            foodie.start();
        }
    }

    运行结果程序一直在走,这是属于正常现象

  • 因为使用阻塞队列时,线程会一直运行是因为线程会阻塞等待队列中有数据可供处理,从而避免线程空转浪费 CPU 资源。

 


  • 09 线程六个状态
    •  
      • JVM没有运行状态
      • 当线程抢夺到CPU的执行权,JVM会把当前线程交给操作系统管理

  • 10 线程池
    • 之前线程的弊端
    • 线程池
      • 核心原理
      • 代码实现
        •  
          • 实际场景:不用关闭线程池
        •  
          • public static ExecutorService newCachedThreadPool()的上限是int最大值
          • 方法补充
            public static ExecutorService newSingleThreadExecutor()                                                 创建一个单线程的线程池
                        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 创建一个固定大小的线程池,支持定时及周期性任务执行
                        public static ExecutorService newWorkStealingPool()                                                     创建一个使用所有可用 CPU 核心数的线程池
                        public static ExecutorService newWorkStealingPool(int parallelism)                               创建一个使用指定并行线程数的线程池*/
            

          • 代码实现
          • public class MyRunnable implements Runnable{
                @Override
                public void run(){
                    for (int i = 0; i <=100; i++){
                        System.out.println(Thread.currentThread().getName()+"#"+i);
                    }
                }
            }

            测试类

          • public class MyThreadPoolDemo {
                public static void main(String[] args) throws InterruptedException {
                    /*  public static ExecutorService newCachedThreadPool()                                                  创建一个没有上限的线程池
                        public static ExecutorService newFixedThreadPool(int nThreads)                                  创建一个固定大小的线程池
                        public static ExecutorService newSingleThreadExecutor()                                              创建一个单线程的线程池
                        public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 创建一个固定大小的线程池,支持定时及周期性任务执行
                        public static ExecutorService newWorkStealingPool()                                                     创建一个使用所有可用 CPU 核心数的线程池
                        public static ExecutorService newWorkStealingPool(int parallelism)                               创建一个使用指定并行线程数的线程池*/
            
            
                    //获取线程池对象
                    ExecutorService pool1 = Executors.newFixedThreadPool(4);
                    //提交任务
                    pool1.submit(new MyRunnable());
                    Thread.sleep(10);
                    pool1.submit(new MyRunnable());
                    Thread.sleep(10);
                    pool1.submit(new MyRunnable());
                    pool1.submit(new MyRunnable());
                    pool1.submit(new MyRunnable());
                    pool1.submit(new MyRunnable());
            
                    //关闭线程池
            //        pool1.shutdown();
                }
            }

      • 自定义线程池
      • 任务拒绝策略
      • 线程池大小
        • 最大并行数
          • 为什么+1
            • 将并行数量设置为CPU核心数量加一可以确保系统的所有核心在任何时候都有任务在执行,避免出现空闲核心的情况,并提高系统的整体效率。
        • 线程池多大合适呢
          • 对于线程池的运行情况可以通过获取线程堆栈信息(thread dump)来进行分析和调优,以解决线程池卡死、线程过多等问题
        • 两种运算方式的使用场景
          • CPU密集型运算:
            • 使用场景:适用于需要大量的算术或逻辑运算的任务,如复杂的数值计算、加密算法、图形渲染等。
            • 例子:科学计算、密码解密、图像处理等。
            • 优化策略:利用多线程、并行计算、CPU优化指令集等方式提高计算效率。
          • IO密集型运算:
            • 使用场景:适用于需要频繁进行输入输出操作的任务,如文件读写、网络请求、数据库查询等。
            • 例子:Web服务器、数据库服务器、文件传输等。
            • 优化策略:使用异步IO操作、缓存、批量处理等方式减少IO等待时间,提高系统的IO吞吐量

标签:JAVA,入门,Thread,void,static,线程,new,多线程,public
From: https://blog.csdn.net/2401_85014515/article/details/140175064

相关文章

  • 【网络安全】简单的免杀方法(非常详细)零基础入门到精通,收藏这一篇就够了_免杀 最难
    一、免杀的概念什么是免杀?免杀,也就是反病毒(AntiVirus)与反间谍(AntiSpyware)的对立面,英文为Anti-AntiVirus(简写VirusAV),逐字翻译为“反-反病毒”,翻译为“反杀毒技术”。通俗点讲,也就是一个被杀软报毒的PE文件,经过一系列处理后,使杀软不认为他是一个病毒或木马。那么,啥是P......
  • [java]windows下jdk安装包所有版本系列下载地址汇总国内源下载
    jdk1.8及其以前版本可以参考[java]windows和linux下jdk1.8安装包所有版本系列下载地址汇总,这里只发布jdk9及其以后最新版本。注意下面均为windowsx64版本安装包exe格式序号java版本下载地址1jdk-22.0.1-windows-x64-bin.exe点我下载2jdk-21.0.3-windows-x64-bin.exe点我下......
  • Java多线程编程
    1.进程进程是指操作系统中正在运行的程序实例,它是系统资源分配的基本单位。每个进程都拥有独立的内存空间和系统资源,可以看作是程序的一次执行过程。2.线程线程是进程中的执行单元,也被称为轻量级进程(LightWeightProcess)。一个进程可以包含多个线程,这些线程共享进......
  • java笔记分享(6)
    RandomRandom类        Random类位于java.util包下,Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。        相同种子数的Random对象,相同次数......
  • 采用Java语言+开发工具 Idea+ scode数字化产科管理平台源码,产科管理新模式
    采用Java语言+开发工具Idea+scode数字化产科管理平台源码,产科管理新模式数字化产科管理系统是现代医疗信息化建设的重要组成部分,它利用现代信息技术手段,对孕产妇的孕期管理、分娩过程及产后康复等各个环节进行数字化、智能化管理,以提升医疗服务质量和效率;以下是对数字化......
  • 基于Java中的SSM框架实现野生动物公益保护系统项目【项目源码+论文说明】计算机毕业设
    基于Java中的SSM框架实现野生动物公益保护系统演示摘要本系统按照网站系统设计的基本流程,遵循系统开发生命周期法和结构化方法,基于Java语言设计并实现了野生动物公益保护系统。该系统基于浏览器/服务器模式,采用JSP技术,后台数据库系统选择MySQL数据库。系统分为前台和后台......
  • java 导出execl 文件实现动态列和列合并
    1.importorg.apache.poi.ss.usermodel.*;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;第一步,判断有几列,放入list ,list一个一个判断,组装列 第二步,放数据的时候同样的逻辑,一列一列判断,放入数据  《2》实现列和行合并和列居中 4.main方法写到本地测试......
  • java高仿真数据生成器-需要的拿去
    java高仿真数据生成器源码-需要的拿去nit-random-tools介绍:高仿真数据生成器逆天开源java证号码,姓名,职业,日期,手机号生成器功能列表编号功能描述class1号生成器NitIdcardGenerator2姓名生成器NitChineseNameGenerator3职业生成器NitJobGenerator4日期生成器N......
  • Java程序员转到AI大模型开发的路线_java转ai
    从Java开发转向AI大模型开发,需要系统地学习和掌握一系列新的技术和算法。以下是一条推荐的学习路线:数学与统计学基础:线性代数:矩阵运算、特征值与特征向量等。概率论与统计学:概率分布、假设检验、最大似然估计、贝叶斯推断等。微积分:梯度求解和优化理论。机器学习入门:......
  • JAVA开发环境的搭建(JDK下载与安装)
    一、什么是JDK、JREJDK(JavaDevelopmentKit):是Java程序开发工具包,包含JRE和开发人员使用的工具。JRE(JavaRuntimeEnvironment):是Java程序的运行时环境,包含JVM和运行时所需要的核心类库。小结:        JDK=JRE+开发工具集(例如Javac编译工具等)        ......