线程的基本使用

线程与进程

在资源管理器中常常可以看到进程和一些进程里面的程序,那么这些是什么呢?接下来我们一起探讨
在这里插入图片描述

线程与进程的基本概念

  • 进程:正在运行的程序,是操作系统分配系统资源(CPU、内存)的最小单位
  • 线程:进程是由多个线程组成的,是操作系统调度CPU的最小单元,每个线程可以单独执行指令

进程与线程的区别

进程更加重量级,操作系统创建和销毁进程需要更多的时间和资源,进程的相互通信更加复杂

线程更加轻量级,操作系统创建和销毁线程消耗时间和资源更少,同一个进程的线程可以共享内存空间,通信更容易

为什么使用多线程

  • 压榨CPU资源,执行高性能运算
  • 同时执行多个程序指令,相互不会影响
  • 服务器可以同时服务多个用户,互不影响

并发与并行

  • 并发:同时执行多个任务,一个CPU内核会在多个线程间来回切换执行程序指令,不是真正同时执行

  • 并行:同时执行多个任务,多个CPU内核,一个内核执行一个线程,线程中指令是同时执行的

同步与异步

  • 同步:多个指令是排队执行的,效率比较低

  • 异步:多个指令同时执行(借助线程),效率比较高

线程的创建

主要通过四种方式创建

  • 继承Thread类
  • 实现Runnable接口
  • 实现Callable接口
  • 线程池

1.继承Thread类,重写run方法,使用start执行

/**
 * 继承Thread类
 */
public class MyThread extends Thread{

    //重写run方法
    @Override
    public void run() {
        //Thread.currentThread() 当前线程
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "执行了" + i);
        }
    }

    public static void main(String[] args) {
        //创建线程,启动线程
        //启动线程使用start,为什么不使用run? 使用start才能创建新的线程执行,使用run方法就是在主线程中执行
        //多线程是如何执行???CPU的调度是抢占式,每个线程去抢cpu资源,执行过程可以被其它线程抢过去
        for (int i = 0; i < 10; i++) {
            MyThread thread = new MyThread();
            thread.start();
        }
        //主方法中执行的线程是main
        System.out.println(Thread.currentThread().getName() + "执行了");
    }
}

2.实现Runnable接口,重写run方法,创建Thread对象时传入Runnble对象,使用start执行

/**
 * 自定义Runnable对象
 * 更加灵活,继承类后不能继承其它类,实现接口没有任何限制
 * 语法更严格,必须重写run方法,继承类后不强制要求
 */
public class MyRunnable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "执行了" + i);
        }
    }

    public static void main(String[] args) {
//        //创建Thread对象,同时传入Runnable对象
//        Thread thread = new Thread(new MyRunnable());
//        //启动线程
//        thread.start();
        //使用lambda表达式实现Runnable
        for(int i = 0; i < 10;i++){
            new Thread(() -> {
                for (int j = 0; j < 100; j++) {
                    System.out.println(Thread.currentThread().getName() + "执行了" + j);
                }
            }).start();
        }
    }
}

3.实现步骤
1)实现callable接口

2) 实现call方法,返回结果

3) 创建FutureTask对象,传入Callable对象

4) 创建Thread对象,传入FutureTask对象

5) 调用Thread的start方法

6) 通过FutureTask的get方法获得返回结果

/**
 * 自定义Callable对象
 */
public class MyCallable implements Callable<Long> {
    @Override
    public Long call() throws Exception {
        long sum = 0;
        //长时间运算
        for (int i = 0; i < 100000000L; i++) {
            sum += i;
        }
        System.out.println(Thread.currentThread().getName()+"运算完毕!");
        return sum;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建FutureTask对象,传入Callable对象
        FutureTask<Long> futureTask = new FutureTask<>(new MyCallable());
        //创建Thread对象,传入FutureTask对象
        Thread thread = new Thread(futureTask);
        //启动线程
        thread.start();
        //获得运算结果
        System.out.println("结果是:" + futureTask.get());
    }
}

继承Thread类和实现Runnable接口的区别

​ 1、继承Thread类不能继承其它类,实现Runnable接口在继承方面没有限制

​ 2、继承Thread类不要求重写run,实现Runnable接口强制要求重写run

​ 推荐使用Runnable

线程的生命周期

  • 新建
  • 就绪
  • 运行
  • 阻塞
  • 死亡
    在这里插入图片描述

线程常用方法

方法名说明
* start()启动线程
stop()停止线程,可能导致重要资源无法释放,出现死锁等问题
interrupt()中断线程,可以配合异常处理停止线程
* run()执行线程的核心指令
setName(String)设置名字
getName()获得名字
* sleep(long)Thread的静态方法,让当前线程睡眠一定时间(毫秒)
* setPriority(int)设置优先级,从低到高,1到10,优先级高的线程抢占cpu几率更高
yield()放弃占用CPU一会,马上回到就绪状态
suspend()禁用,当前线程挂起(暂停)
resume()禁用,当前线程恢复
* setDaemon(boolean)设置后台线程,默认是false
join()合并其它线程,让其它线程先执行完,再执行自己的代码

如何停止线程?

1) stop 禁用,可能导致重要资源无法释放,出现死锁等问题

2) 等待run方法执行结束

3) 在run方法加入条件,中途停止run方法

4) 执行interrupt方法,进行异常处理的时候停止线程

什么是后台线程?

后台线程是一种特殊线程,这种线程是为其它线程服务的,如果没有存活的其它线程,后台线程会自动死亡

后台线程主要应用场景:GC 垃圾收集器 就是一种后台线程

sleep和wait的区别

都可以让线程进入阻塞状态

区别:

  • 调用对象不同:sleep是线程调用的,wait是锁对象(Object)调用的
  • 释放锁不同:sleep不会让线程释放锁,wait会让线程释放锁
  • 唤醒机制不同:sleep只能等睡眠时间结束,wait可以等时间结束也可以通过notify方法唤醒
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值