多线程

本文详细介绍了Java中多线程的基本概念,包括进程与线程的区别、多线程的实现方式及其优缺点,并通过实例展示了如何创建和启动线程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程

进程

正在运行中的程序就是一个进程。

确切的来说,当一个程序进入内存运行,即是一个或多个进程在运行,具有一定独立功能

线程
线程是进程中的一个执行单元,执行路径。是程序使用CPU的最基本单位。

负责当前进程中程序的执行, 程序的执行其实都是在抢CPU的资源,CPU的执行权。

一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

线程的分类
    * 单线程:同一时间只能干一件事情。
    * 多线程:同一时间可以干多件事情。Java是属于多线程程序
    
多线程的优缺点:

多线程并不能提高运行速度,但可以提高运行效率,让 CPU 的使用率更高。

并且,如果多线程有安全问题的处理时,运算速度反而更低。

进程和线程的作用

  进程:用来封装线程的,为线程运行提供资源(内存)

  线程:用来执行代码的

Java 中的多线程


A:java 支持多线程

B: java 程序执行 main 方法的时候,就是在执行一个名字叫做 main 的线程.
    
 可以在 main 方法执行时,开启多个线程 A,B,C
 
 多个线程 main,A,B,C 同时执行,相互抢夺 CPU
 
C:Thread 类是 java.lang 包下的一个常用类,每一个 Thread 类的对象,就代表一个处于某种状态的线程.

主线程和子线程的概念

主线程的概念
    * 什么是主线程
        * 程序启动时系统自动创建并执行main方法的线程则称为主线程。
    * 主线程的执行路径
        * 从main方法开始直到main结束。    
子线程的概念
    * 什么是子线程
        * 除了主线程以为的所有线程都称为子线程。
    * 子线程的执行路径
        * 从run方法开始直到run方法结束。

线程的运行模式


* 分时式模式:每个线程平均分配CPU的使用权。

* 抢占式模式:优先级高的线程会有更高的几率抢到CPU的执行权。我们是不敢保证哪一个线程能够在哪个时刻抢到
    
Java程序的线程运行模式是属于抢占式模式。

jvm虚拟机的启动是单线程的还是多线程的?

多线程的。

原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。

现在的垃圾回收线程加上前面的主线程,最低启动了两个线程,所以,jvm的启动其实是多线程的。

Thread 类的一些方法:


public final String getName() 获取线程名称

public final void setName(String name) 指定线程名称

public static Thread csurrentThread() 获得当前方法执行所在的线程对象。

static void sleep(long millis)  让当前方法执行所在的线程休眠指定的毫秒数。

继承 Thread 类创建线程

1,指定线程执行目标:定义一个 Thread 类的子类,重写 run 方法,将相关逻辑实现 public void run()

线程要执行的业务逻辑方法,相当于该想成的"main 方法"

2,创建自定义的线程子类对象

3,调用start方法开启线程。

public void start() 使该线程开始执行

//指定线程执行目标:定义一个 Thread 类的子类,重写 run 方法,将相关逻辑实现 public void run()
public class MyThread extends Thread {
    
    @Override
    public void run() {
        int num=0;
        while(num<100){
            try {
                Random ra=new Random();
                
                // 让线程休眠4s
                Thread.sleep(ra.nextInt(4000));
                
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("一个子线程"+this.getName()+"在运行:"+num++);
        }
        
        
    }
    
}


    //创建自定义的线程子类对象
    MyThread t1=new MyThread();

    // 设置线程名称
    t1.setName("子线程(1)");

    //开启线程动作
    t1.start();
        
    MyThread t2=new MyThread();
    t2.setName("子线程(2)");       
    t2.start();

实现 Runnable 接口创建线程

* 创建一个类实现Runnable接口

* 重写Run方法,将线程任务相关代码写在该方法中

* 创建Runnable接口实现类对象

* 根据实现类对象创建Thread类对象,调用start方法

public class MyRunnable implements Runnable {
    
    private int number = 1;
    
    @Override
    public void run() {
                
        //返回当前线程
        Thread thisThread = Thread.currentThread();
        
        int num=1;
        
        while(number<10){
            try {
                Random ra=new Random();
                                
                Thread.sleep(ra.nextInt(4000));
                
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("一个子线程"+thisThread.getName()+"在运行:"+num++);
            System.out.println("目标运行次数:"+number++);                     
        }
        
    }

         //创建Runnable接口的实现类对象
        MyRunnable mr = new MyRunnable();
        
        // 创建线程对象
        Thread thread = new Thread(mr);
        thread.setName("子线程(3)");
        
        
        Thread thread2 = new Thread(mr);
        thread2.setName("子线程(4)");
        
        //开启线程
        thread.start();
        thread2.start();

实现Runnable接口的好处

  • 屏蔽的Java类单继承的局限性。

  • 可以更好的实现资源共享。

  • 将线程和任务进行了分离,降低了程序的耦合性。

两种实现方式对比
A:第二种方式实现 Runnable 接口避免了单继承的局限性,所以较为常用。 

B:实现 Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。

继承 Thread 类,线程对象和线程任务耦合在一起。

一旦创建 Thread 类的子类对象,既是线程对象,有又有线程任务。

实现 runnable接口,将线程任务单独分离出来封装成对象,类型就是 Runnable 接口类型。

Runnable 接口对线程对象和线程任务进行解耦。

使用匿名内部类创建线程

    //方式一:
        //使用匿名内部类创建线程的子类对象
        Thread thread = new Thread() {
        @Override
        public void run() {
        System.out.println("我执行了线程1");
        }
        };
        thread.start();
        
        //使用匿名内部类创建线程的子类匿名对象
        new Thread() {
        @Override
        public void run() {
        System.out.println("我执行了线程2");
        }
        }.start();
        
        
    //方式二:
        //使用匿名内部类的方式,创建线程执行目标类对象
        //创建线程执行目标类对象
        
        Runnable runnable = new Runnable() {
        @Override
        public void run() {
        System.out.println("我执行线程目标1");
        }
        };
        
        
        //通过目标创建线程对象
        Thread thread2 = new Thread(runnable);
        //开启线程
        thread2.start();
        
    //方式三:  
        //使用匿名内部类的方式,创建线程执行目标类匿名对象
        //创建线程执行目标类对象
        //通过目标创建线程对象
        Thread thread3 = new Thread(new Runnable() {
        @Override
        public void run() {
        System.out.println("我执行线程目标2");
        }
        });
        //开启线程
        thread3.start();
        
    //方式四:
        //使用匿名内部类的方式,创建线程执行目标类匿名对象,并且创建的是线程的匿名对象
        //创建线程执行目标类对象
        //通过目标创建线程对象
        
        new Thread(new Runnable() {
        @Override
        public void run() {
        System.out.println("我执行线程目标3");
        }
        }).start();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值