进程与线程

本文详细介绍了进程和线程的概念,包括进程是系统资源分配的基本单位,线程是执行路径,以及多线程的实现方式,如继承Thread类和实现Runnable接口。此外,还讨论了线程的调度模型、优先级设置、线程名字的管理以及线程控制方法如sleep()和join()。

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

1、进程

  • 进程是正在运行的程序;

  • 是系统进行资源分配和调用的独立单位

  • 每一个进程都有自己的内存空间和系统资源

2、线程

2.1、线程的说明

线程:是进程中的单个顺序控制流,是一条执行路径

  • 单线程:一个进程如果只有一条执行路径,则称为单线程程序

  • 多线程:一个进程如果有多条执行路径,则称为多线程程序

2.2、多线程的实现方式:

方式一:继承Thread类

  • 1:定义一个类MyThread继承Thread类

  • 2:在MyThread类中重写run()方法

  • 3:创建My Thread类的对象

  • 4:启动线程

两个小问题:

  • a、为什么要重写run()方法?

因为run()是用来封装被线程执行的代码

  • b、run()方法和start()方法的区别?

run():封装线程执行的代码,直接调用,相当于普通方法的调用

start():启动线程;然后由JVM调用此线程的run()方法

方式二:实现Runnable接口

  • 定义一个类MyRunnable实现Runnable接口

  • 在MyRunnable类中重写run()方法

  • 创建MyRunnable类的对象

  • 创建Thread类的对象,把MyRunnable对象作为构造方法的参数

  • 启动线程

相比继承Thread类,实现Runnable接口的好处

  • 在实现多线程的时候还可以去继承其他的类

  • 避免了Java单继承的局限性

  • 适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想

代码实现:

创建一个MyRunnable实现Runnable接口

package 线程;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //这里不能直接使用getName()来获取线程名字,因为这只是实现了Runnable接口而已
            System.out.println(Thread.currentThread().getName()+"\t"+i);
        }
    }
}

创建一个实现类

package 线程;
​
/**
 *方式二:实现Runnable接口
 *
 *       定义一个类MyRunnable实现Runnable接口
 *
 *       在MyRunnable类中重写run()方法
 *
 *       创建MyRunnable类的对象
 *
 *       创建Thread类的对象,把MyRunnable对象作为构造方法的参数
 *
 *       启动线程
 */
public class MyRunnableDemo {
    public static void main(String[] args) {
        //创建MyRunnable类的对象
        MyRunnable mr=new MyRunnable();
​
        //创建Thread类的对象,把MyRunnable对象作为构造方法的参数
        Thread t1=new Thread(mr,"张三");
        Thread t2=new Thread(mr,"李四");
​
        //启动线程
        t1.start();
        t2.start();
​
​
    }
}

2.3、设置和获取线程名字

setName() 方法是用来给线程添加名字的

getName() 方法是用来获取线程的名字的,当没给线程赋值一个名字时,线程是使用默认的名字 Thread-0后面的数字从零开始

例题:

1、创建一个线程类:

package 线程;
​
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 15; i++) {
            System.out.println(getName()+"\t"+i);
        }
    }
}

2、编写一个实现类:

package 线程;

/**
 * 方式1:继承Thread类
 * 1:定义一个类MyThread继承Thread类
 * 2:在MyThread类中重写run()方法
 * 3:创建My Thread类的对象
 * 4:启动线程
 */
public class MyThreadDemo {
    public static void main(String[] args) {
        //currentThread()方法是用来获取当前执行的线程名字
        System.out.println(Thread.currentThread().getName());

        //创建两个线程对象
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();

        //setname()方法给线程赋值名字,若没有赋值名字就会产生默认名字  Thread-第几个,从0开始;
        //getname()方法是用来获取线程名字的

        //给线程添加名字
        mt1.setName("飞机");
        mt2.setName("大炮");


        //运行线程
        mt1.start();
        mt2.start();


    }
}

2.4、线程的调度

线程有两种调度模型

  • 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片

  • 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些

  • Java使用的是抢占式调度模型。

2.5、线程的优先级

Tread类的设置和获取线程优先级的方法

  • getPriority()方法是用来返回此线程的优先级

  • setPriority()方法是用来修改此线程的优先级

注意:

  • 线程的优先级默认值是:5,线程优先级的范围是:1-10;

  • 线程优先级高仅仅表示线程获取的CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果,不是每一次线程优先级高的都在最前面;

package 线程;
​
/**
 * Thread类中设置线程的优先级
 * getPriority()方法是用来返回此线程的优先级
 * setPriority()方法是用来修改线程的优先级的
 */
public class MyThreadDemo02 {
    public static void main(String[] args) {
        //创建两个线程对象
        MyThread mt1=new MyThread();
        MyThread mt2=new MyThread();
        MyThread mt3=new MyThread();
​
        //给线程添加名字
        mt1.setName("飞机");
        mt2.setName("大炮");
        mt3.setName("java");
​
        //getPriority()方法是用来返回此线程的优先级
//        System.out.println(mt1.getPriority());
//        System.out.println(mt2.getPriority());
//        System.out.println(mt3.getPriority());
​
        //setPriority()方法是用来修改线程的优先级的
        //线程的默认优先级是 5 ,最大优先级是 10 ,最小优先级是 1
//        System.out.println(Thread.MAX_PRIORITY);  // 10
//        System.out.println(Thread.MIN_PRIORITY);  // 1
//        System.out.println(Thread.NORM_PRIORITY); // 5
​
        //优先级高是获取CPU资源的概率高,并不是每一次都会在前面
        mt1.setPriority(1);
        mt2.setPriority(10);
        mt3.setPriority(9);
​
        //运行线程
        mt1.start();
        mt2.start();
        mt3.start();
    }
}

2.6、线程控制

方法说明
static void sleep(long millis)使当前正在执行的线程停留(暂停执行)指定的毫秒数,是指运行完一个线程后,暂停的秒数
void join()等待这个线程死亡
void setDaemon(boolean on)将此线程标记为守护线程,当运行的线程都是守护线程的时,Java虚拟机将退出
currentThread()设置一个主线程

static void sleep(long millis) 方法的使用:

当一个线程执行完之后需要需要等其他线程都执行完之后才能执行,就是需要一个同步线程的时候,可以用来这个方法来设置休息毫秒数来控制;

案例:

1、线程实现类

package 线程;
​
/**
 * sleep方的使用案例
 *当线程需要每一个都执行一次的时候可以使用,
 * 就是需要线程每个都能执行一次,才能在执行
 * 就是要求 曹操 刘备 孙权 当一个执行后,要等其他两个执行完之后才能在执行
 */
public class MyTreadSleep_Demo {
    public static void main(String[] args) {
        //创建两个线程对象
        MyTreadsleep mt1=new MyTreadsleep();
        MyTreadsleep mt2=new MyTreadsleep();
        MyTreadsleep mt3=new MyTreadsleep();
​
        //setname()方法给线程赋值名字,若没有赋值名字就会产生默认名字  Thread-第几个,从0开始;
        //getname()方法是用来获取线程名字的
​
        //给线程添加名字
        mt1.setName("刘备");
        mt2.setName("曹操");
        mt3.setName("孙权");
​
        //运行线程
        mt1.start();
        mt2.start();
        mt3.start();
    }
}

2、线程:

package 线程;
​
public class MyTreadsleep extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 15; i++) {
            System.out.println(getName()+"\t"+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
​

void join() :方法的使用,当需要一个线程执行完,其他线程才能执行时,就可以这个方法;

package 线程;
​
/**
 * join方法的使用案例:
 * 当康熙死后,四阿哥和八阿哥才能抢位置
 * 及当康熙线程执行完之后,四阿哥和八阿哥两个线程才能执行
 */
​
public class MyThreadDemo03 {
    public static void main(String[] args) {
        //创建两个线程对象
        MyTreadJoin mt1=new MyTreadJoin();
        MyTreadJoin mt2=new MyTreadJoin();
        MyTreadJoin mt3=new MyTreadJoin();
​
        //给线程添加名字
        mt1.setName("康熙");
        mt2.setName("四阿哥");
        mt3.setName("八阿哥");
​
        //运行线程
        mt1.start();
​
        try {
            mt1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
​
        mt2.start();
        mt3.start();
    }
}
​

void setDaemon(boolean on)的方法使用案例:

package 线程;
​
/**
 * 守护线程的案例,
 * void setDaemon(boolean on)的方法使用案例;
 * 当刘备线程执行完之后,关羽和张飞线程就不再执行了,这就需要将关羽和张飞设置为守护线程
 *
 */
public class setDaemon_Demo {
    public static void main(String[] args) {
        //创建两个线程对象
        MyTreadJoin mt2=new MyTreadJoin();
        MyTreadJoin mt3=new MyTreadJoin();
​
        //给线程添加名字
        mt2.setName("关羽");
        mt3.setName("张飞");
​
        mt2.setDaemon(true);
        mt3.setDaemon(true);
​
        //设置主线程,当主线程执行完成之后,守护线程会在执行一段才会关闭
        Thread.currentThread().setName("刘备");
​
        //运行线程
​
        mt2.start();
        mt3.start();
​
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"\t"+i);
        }
    }
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值