JavaSE_21_线程(一)

本文介绍了Java中的线程概念,包括程序、进程和线程的区别。详细讲解了主线程以及多线程的应用,通过装箱水果的场景模拟展示了单线程和多线程的执行差异。同时,文章提到了线程的创建方式,如继承Thread类和实现Runnable接口,并讨论了线程状态和结束线程的策略,包括修改标志、interrupt方法和引发异常。

《线程(一)》

目录

  • 线程概念(掌握)
  • 线程创建(熟练)
  • 线程状态(掌握)
  • 结束线程(熟练)

一、线程概念

程序、进程、线程

程序:一堆命令的集合,进程的静止的状态,包括了可执行文件、配置文件、数据文件等等软件文件集合;

进程:程序运行期间的动态状态,占用内存、占用CPU等系统资源;

线程:进程下的最小的执行单元,多任务处理的最基本的执行单元。

请添加图片描述

主线程

在Java程序启动时,一个线程立刻运行,该线程通常称为程序的主线程;主线程的重要性体现在两个方面:

  1. 它是产生其他子线程的线程(但不一定负责关闭子线程);
  2. 通常它必须最后完成执行(除了守护线程之外),因为它执行各种关闭动作。

请添加图片描述

多线程

  1. 在Java中,一个应用程序可以包含多个线程。每个线程执行特定的任务,并可与其他线程并发执行;
  2. 多线程使系统的空转时间最少,提高CPU利用率;
  3. 多线程编程环境用方便的模型隐藏CPU在任务间切换的事实。

二、线程创建

主线程测试(main)

package com.hpr.test;

public class Test {
    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        System.out.println("当前线程:" + t.getName());
        t.setName("主线程");
        System.out.println("当前线程:" + t.getName());
    }
}

执行结果

请添加图片描述

多线程应用(场景模拟)

果园要出口水果,用户下单要10W苹果跟10W梨,这个时候安排工作人员去装箱。

请添加图片描述

案例一(单线程处理)

package com.hpr.test;

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        //装苹果
        List<String> appleList = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            appleList.add("apple" + i);
        }
        //装梨
        List<String> pearList = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            pearList.add("pear" + i);
        }
        System.out.println("单线程:10W苹果+10W梨装箱完成!");
    }
}

执行结果

请添加图片描述

线程创建方式

  • 继承Thread类,重写run方法
  • 实现Runnable接口,实现run方法

案例二(多线程处理)

  • TestThread类
package com.hpr.test;


import java.util.ArrayList;
import java.util.List;

public class TestThread {

    /**
     * 苹果线程
     */
    static class AppleThread extends Thread {
        @Override
        public void run() {
            List<String> appleList = new ArrayList<>();
            for (int i = 0; i < 100000; i++) {
                appleList.add("apple" + i);
            }
            System.out.println(Thread.currentThread().getName() + ":10W苹果装箱完成!");
        }
    }


    /**
     * 梨线程
     */
    static class PearThread implements Runnable {
        @Override
        public void run() {
            List<String> pearList = new ArrayList<>();
            for (int i = 0; i < 100000; i++) {
                pearList.add("pear" + i);
            }
            System.out.println(Thread.currentThread().getName() + ":10W梨装箱完成!");
        }
    }

    public static void main(String[] args) {
        AppleThread th1 = new AppleThread();
        th1.setName("苹果线程");
        th1.start();

        Thread th2 = new Thread(new PearThread());
        th2.setName("梨线程");
        th2.start();

        System.out.println(Thread.currentThread().getName() + ":正在执行...");
    }

}

执行结果

多线程默认情况下是异步的(即各做各的)。

请添加图片描述

加入线程(优先执行)

修改上述代码:

public static void main(String[] args) {
    ...
    try {
        //加入线程(优先执行)
        th1.join();
        th2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + ":正在执行...");
}

执行结果

请添加图片描述

三、线程状态

Thread重要方法

void start()					//启动线程

void setPriority(int p)			//设置线程优先级1~10

void interrupt()				//有条件中断线程

void sleep(long s)				//线程休眠,可指定让出cpu资源时长

Thread currentThread()			//获取执行当前内容的线程

boolean isAlive()				//判断线程是否在活动状态

void yield()					//临时让出cpu资源

void setDaemon(boolean b)		//设置是否是守护线程

void join()						//加入其他线程,即优先执行
    
void wait()						//Object方法,使当前线程处于等待状态

void notify()					//Object方法,随机唤醒一个等待状态线程
    
void notifyAll()				//Object方法,唤醒所有等待状态线程

Thread状态

  • 新建 (Born) : 新建的线程处于新建状态;
  • 就绪 (Ready) : 在创建线程后,它将处于就绪状态,等待 start() 方法被调用;
  • 运行 (Running) : 线程在开始执行时进入运行状态;
  • 睡眠 (Sleeping) : 线程的执行可通过使用 sleep() 方法来暂时中止。在睡眠后,线程将进入就绪状态;
  • 等待 (Waiting) : 如果调用了 wait() 方法,线程将处于等待状态。用于在两个或多个线程并发运行时;
  • 挂起 (Suspended) : 在临时停止或中断线程的执行时,线程就处于挂起状态;
  • 恢复 (Resume) : 在挂起的线程被恢复执行时,可以说它已被恢复;
  • 阻塞 (Blocked) – 在线程等待一个事件时(例如输入/输出操作),就称其处于阻塞状态;
  • 死亡 (Dead) – 在 run() 方法已完成执行或其 stop() 方法被调用之后,线程就处于死亡状态。

四、结束线程

结束线程就是让线程的run方法执行完毕,而不是使用stop()或者destroy()方法,可使用以下三种方式:

  • 修改标志
  • interrupt()
  • 引发异常

修改标志(适用于无阻塞线程)

package com.hpr.test;

public class Test1 {
    static class OverThread extends Thread {
        //标志变量,默认为true
        boolean flag = true;

        //提供外部设置方法
        public void setFlag(boolean flag) {
            this.flag = flag;
        }

        @Override
        public void run() {
            int i = 0;
            while (flag) {
                try {
                    Thread.sleep(1000);
                    System.out.println(i++);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("子线程运行结束!");
        }
    }

    public static void main(String[] args) {
        //启动子线程
        OverThread th = new OverThread();
        th.start();
        try {
            //主线程休眠3秒后修改子线程标志为false
            Thread.sleep(3000);
            th.setFlag(false);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

执行结果

请添加图片描述

interrupt打断(适用于休眠或等待线程)

//此类线程只要调用interrupt()方法就可以终止线程
public void run() {
    while (!this.isInterrupted()) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
    }
}

引发异常(适用于阻塞,如监听连接、文件流操作)

public void run() {
    byte[] b = new byte[1024];
    while (true) {
        try {
            //is是输入流
            int len = is.read(b);
            //其他代码
        } catch (IOException e) {
            //发生异常,打断循环,线程也就结束了
            break;
        }
    }
}

总结

重点

  1. 程序、进程、线程相关概念;
  2. 主线程与多线程;
  3. 线程相关方法及状态;
  4. 结束线程的三种方式。

难点

  1. 线程相关方法及状态。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值