• JAVA多线程


    一、相对于多进程,多线程的优势如下:

    1、 进程之间不能共享数据,线程可以
    2、系统需要为新创建的进程重新分配系统资源,而创建线程代价较小。
    3、java内置多线程功能,简化编程。

    二、线程的创建和启动有三种方式:

    2.1、继承Thread类创建线程类

    1、定义一个继承Thread类的子类,重写run()方法
    2、创建Thread子类的实例。
    3、调用start()方法启动线程

     public class FirstThread extends Thread{
    
        @Override //重写Thread的run方法
        public void run(){
            System.out.println("继承Thread");
         }
     }
    
    
     public class Test {
     
        public static void main(String[] args) {
            FirstThread firstThread = new FirstThread();//线程对象
            firstThread.start();
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.2、实现Runnable接口创建线程类
    1、定义Runnable接口的实现类,重写接口的run()方法
    2、创建Runnable实现类的实例,以此作为Thread的target对象,所以Thread对象才是真正的线程对象。
    3、调用start()方法启动线程

     public class FirstRunnable implements Runnable{
    
        @Override //重写Thread的run方法
        public void run(){
            System.out.println("实现 Runnable 接口");
         }
     }
    
     public class Test {
        public static void main(String[] args) {
            FirstRunnable firstRunnable = new FirstRunnable();//firstRunnable作为Thread的target对象
            Thread firsrThread =new Thread(firstRunnable);
            firsrThread.start();
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.3、通过Callable和Future创建线程
    1、创建Callable接口的实现类,并实现call()方法(作为线程的执行体,有返回值)。
    2、创建Callable实现类的实例,并使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
    3、将FutureTask对象作为Thread对象的target,创建该Thread对象并启动新线程。
    4、调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

     public class FirstCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("first Callable");
            return "first Callable";
          }
      }
    
     public class Test {
        public static void main(String[] args) {
    
        Callable<String> callable = new FirstCallable();//创建Callable 实例
        FutureTask<String> task = new FutureTask<>(callable);//FutureTask包装Callable 对象
        Thread thread = new Thread(task);
    
         try {
             thread.start();
             System.out.println("return: "+ task.get());
         } catch (InterruptedException e) {
            e.printStackTrace();
         } catch (ExecutionException e) {
            e.printStackTrace();
         }
       }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    三、线程三种创建方式的比较

    3.1、使用继承Thread类的方式创建多线程时:

    优势
    编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。
    劣势:
    线程类已经继承了Thread类,所以不能再继承其他父类。

    3.2、采用RUnnable和Callable接口的方式创建多线程时:

    优势:
    线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
    劣势:
    编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

    3.3、Runnable和Callable的区别:

    1、Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
    2、Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
    3、Call方法可以抛出异常,run方法不可以。
    4、运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。

    四、示例

    4.1、extends Thread

    public class Start1 {
        public static void main(String[] args) {
    
        StartThread1 wugui = new StartThread1();
        StartThread1 tuzi =new StartThread1();
    
       //设置线程优先级
        wugui.setPriority(1);
        tuzi.setPriority(10);
    
       //设置线程名称
        wugui.setName("乌龟线程");
        tuzi.setName("兔子线程");
    
      //启动线程
       wugui.start();
       tuzi.start();
    }
    
    
    public class StartThread1 extends Thread{
    
        public  void run(){
            Thread thread = Thread.currentThread();
            System.out.println(thread.getName());//打印线程调用的名称
            System.out.println(thread.getPriority());//优先级
            for(int i=0;i<100;i++){
                System.out.println(getName()+"跑到了第"+i+"米");
                if ( i==98&&thread.getName().equals("兔子线程")){
                    System.out.println("兔子睡着了");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    4.2、implements Runnable

     public class Test {
        public static void main(String[] args) {
            FirstRunnable firstRunnable = new FirstRunnable();
    
            Thread tuzi = new Thread(firstRunnable);//将任务对象放入线程对象中
            Thread wugui =new Thread(firstRunnable);
    
            tuzi.setName("小兔子线程");   //改变线程名称
            wugui.setName("小乌龟线程");
    
            tuzi.setPriority(9);//线程优先级
            wugui.setPriority(1);//线程优先级
    
            tuzi.start();
            wugui.start();
         }
     }
    
     public class FirstRunnable implements Runnable{
         @Override //重写Thread的run方法
         public void run(){
             Thread thread = Thread.currentThread();
             for ( int i=1;i<=100;i++) {
             
                System.out.println(thread.getName()+"跑到了第"+i+"米");
               try {
                   if ( i==99&&thread.getName().equals("小兔子线程")){
                       System.out.println("小兔子睡着了----");
                       Thread.sleep(5000);
                   }
               }catch (Exception e){
                   e.printStackTrace();
                }
             }
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    【从零开始学习 SystemVerilog】3.1.1、SystemVerilog 控制流—— while 和 do-while 循环
    java计算机毕业设计ssm基于H5的音乐播放管理系统
    SpringBoot + Flyway,自动化实现数据库版本控制
    深蓝激光slam理论与实践-第一节笔记
    C++ c++11(上)
    Git --》如何玩转Gitee?
    java计算机毕业设计高校招生管理系统MyBatis+系统+LW文档+源码+调试部署
    【rust/esp32】wsl2开发环境搭建与测试
    Mysql存储过程和游标的一点理解
    基于微信小程序新冠疫苗预约系统(微信小程序)
  • 原文地址:https://blog.csdn.net/weixin_45663614/article/details/134286480