Java基础第23讲:多线程

一、多线程到底是什么?

1.1、在生活中

  • 对于一个人而言,可以一边看电影,一边吃爆米花
  • 对于一个程序员而言,可以一边敲代码,一边听音乐
  • 对于一对热恋的情侣而言,可以手牵着手肩并着肩,喝着红酒吃着炸鸡,聊着人生,漫步人生路

1.2、在程序中

多线程可以让程序具备多个并发的执行操作,类似于团队协作,多个人合作完成一个任务,这样一来可以大大提高效率,提高资源的利用率

二、线程的生命周期,从生到死,我这一生都经历了什么?

线程是存在生命周期的。线程的生命周期分为5中不同的状态,由始至终分别是:

 

2.1、新建状态

处于新建状态中的线程对象,并不是一个独立的线程,无法运行,只有当被触发start方法时才会进入准备状态。新建状态是线程生命周期中的第一个状态,也是初始状态

2.2、准备状态

处于新建状态的线程对象,被调用了start方法,将进入准备状态;处于准备状态的线程随时都可能被系统选中进入运行状态,从而执行线程;可能同时有多个线程处于准备状态,然而究竟哪一个线程将进入运行状态,这是不确定的;

被阻塞的线程再次被唤醒时,并不会进入运行状态,而是进入准备状态,等待运行时机;

2.3、运行状态

处于准备状态中的线程一旦被系统选中,获得了运行时机,就会进入运行状态;在运行状态中,程序将执行线程类中run方法中的语句块;处于运行状态的线程,可以随时被设置为阻塞状态;

在单核CPU中,同一时刻只能有一个线程处于运行状态。在多核CPU中就可以多个线程同时处于运行状态,这也是多核CPU运行速度快的原因

2.4、等待(阻塞)状态

        Java中提供了许多线程调度的方法,包括睡眠、阻塞、挂起和等待,使用这些方法都会将处于运行状态的线程调度到阻塞(等待)状态。处于阻塞状态的线程被解除后,并不会直接进入运行状态,而是进入准备状态,等待运行时机

2.5、死亡状态

当程序的run方法执行结束后,或程序发生异常终止运行后,线程会进入死亡状态。

三、如何让自己的程序实现多线程?

3.1、如何创建线程对象?

3.1.1、继承Thread类

继承Thread类的子类具备了多线程的能力,重写Thread类的run方法,当线程被启动的时候,run方法中的程序就成为了一条独立的执行线程

示例:

public class NumberThread extends Thread {

    public CalThread(String name){
        setName(name); //给当前线程取名
    }
    /**
     * 线程start()方法操作的方法
     */
    @Override
    public void run() {
        for(int i=0; i<100; i++){
            String name = getName(); //获取当前线程的名称
            System.out.println(name + "==" + i);
        }
    }
}

@Test
public void test1(){
    NumberThread cal = new NumberThread("老司机线程");
    cal.start(); //启动线程
}

3.1.2、实现Runnable接口

实现Runnable接口,需要实现Runnable接口中提供的run方法,当线程被启动的时候,run方法中的程序就成为了一条独立的执行线程

示例:

public class NumberThread implements Runnable {
    private String name;
    public NumberThread(String name){
        this.name = name;
    }   

    /**
     * 线程start()方法操作的方法
     */
    @Override
    public void run() {
        for(int i=0; i<100; i++){
             System.out.println(name + "==" + i);
        }
    }
}

@Test
public void test2(){
    NumberThread number = new NumberThread("老司机线程");
    Thread t = new Thread(number);
    t.start(); //启动线程
}

3.2、如何启动线程?

Java中对于线程后,可以保证的只是让每个线程都启动,并且会执行结果,但是无法决定多个线程中哪个先执行,哪个后执行

四、如何控制(调度)线程?

4.1、睡眠的方法

当线程处于运行状态时,调用sleep方法将使线程从运行状态进入阻塞状态,从而使程序中断运行。该方法是使正在运行的线程让出CPU最简单的方法之一

示例:

public class NumberThread implements Runnable {
    private String name;

    public NumberThread(String name){
        this.name = name;
    }
    /**

     * 线程start()方法操作的方法

     */
    @Override
    public void run() {
        for(int i=0; i<5; i++){
            System.out.println(name + "==" + i);
            try {
                 Thread.sleep(1*1000); //让线程睡眠1秒钟
            } catch (InterruptedException e) {
                 e.printStackTrace();
            }
        }
    }
}
@Test
public void test2(){
    NumberThread number = new NumberThread("老司机线程");
    Thread t = new Thread(number);
    t.start(); //启动线程
}

4.2、让步的方法

Yield方法可以使当前正在运行的线程让出当前CPU,使线程由运行状态回到准备状态,让其他线程有进入运行状态的机会;然而将CPU让给哪一个线程是不确定的

示例:

public class YieldThread extends Thread { 
    public YieldThread(String name) { 
        super(name); 
    } 

    @Override 
    public void run() { 
        for (int i = 1; i <= 50; i++) { 
            System.out.println("" + this.getName() + "-----" + i); 
            // 当i为30时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行) 
            if (i == 30) { 
                yield(); 
            } 
        } 
    }  
} 

public static void main(String[] args) {
    YieldThread yt1 = new YieldThread("张三");
    YieldThread yt2 = new YieldThread("李四");
    yt1.start();
    yt2.start();
}

第一种情况:李四线程当执行到第30时会让出CPU时间,这时张三线程会抢到CPU时间并执行

 第二种情况:李四线程执行到第30时会让出CPU时间,又重新抢到了CPU时间

五、综合案例:费玉清去健身房

/**
 * 费玉清
 *
 * @author qin
 */
public class FeiYuqing extends Thread {
    @Override
    public void run() {
        int race = 100;
        while(race > 0){
            try {
                int x = (int) (Math.random()*20);
                if(race - x >= 0){
                    race = race - x;
                    sleep(1*1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("¥费玉清还有"+race+"米就逃跑成功啦");
        }
        System.out.println("**********费玉清逃跑成功");
    }
}

/**
 * 大猩猩
 *
 * @author qin
 */
public class Chimpanzee extends Thread {

    @Override
    public void run() {
        int race = 100;
        while(race > 0){
            try {
                int x = (int) (Math.random()*20);
                if(race - x >= 0){
                    race = race - x;
                    sleep(1*1000);
               }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("!大猩猩还有"+race+"米就抓到费玉清啦");
        }
        System.out.println("**********大猩猩抓到了费玉清,祝你们幸福");
    }
}

/**
 * 健身房
 *
 * @author qin
 */
public class Gym {

    public static void main(String[] args) {
        FeiYuqing fei = new FeiYuqing();
        fei.start(); //费玉清跑
        Chimpanzee chi = new Chimpanzee();
        chi.start(); //大猩猩追
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值