多线程-初阶(一)

1.线程(Thread)

进程是系统分配资源的最小单位,线程是系统调度的最小单位。一个进程内的线程之间是可以共享资源的。
每个进程至少有一个线程存在,即主线程

(1)面试题:进程VS线程

1.进程是系统分配资源的最小单位;线程是系统调度的最小单位。
2.一个进程中可以包含多个线程,并且至少包含一个线程(主线程)。
3.线程的存储必须依赖于进程。
4.进程的实际执行单位是线程。
5.进程不可以共享资源,而线程可以共享资源。
6.进程有自己的内存地址空间,线程只独享指令流执行的必要资源,如寄存器和栈。
7.线程的创建、切换及终止效率更高。

(2)线程的创建方式

①方式一:继承Thread类

// 写法1:
    static class MyThread extends Thread {
        @Override
        public void run() {
            // 写你的业务代码
            // 打印当前线程的名称
            System.out.println("子线程名称:" +
                    Thread.currentThread().getName());
        }
    }
 //写法2:
 Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("当前线程名称:" +
                        Thread.currentThread().getName());
            }
        };
        // 运行线程
        thread.start();

缺点:因为Java语言的设计式单继承的,当我继承了Thread类之后,就不能继承其他类。

②方式二:实现Runnable接口

//写法3:
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程名:" +
                Thread.currentThread().getName());
    }
}

public class ThreadDemo5 {
    public static void main(String[] args) {
        // 创建 Runnable 子对象
        MyRunnable myRunnable = new MyRunnable();
        // 创建线程
        Thread thread = new Thread(myRunnable);
        // 启动线程
        thread.start();
    }
}

//写法4:
// 创建一个匿名 Runnable 类
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("当前线程:" +
                        Thread.currentThread().getName());
            }
        });
        thread.start();
        
//写法5:
// lambda + runnable  (只有JDK 1.8+才支持)
        Thread thread = new Thread(() -> {
            System.out.println("线程名:" +
                    Thread.currentThread().getName());
        });
        thread.start();

③方式三:Callable+Future接收线程执行之后的返回值

/**
 * 创建一个有返回值的线程
 */
public class ThreadDemo8 {
    // 创建线程,Callable可以返回进程的结果
    static class MyCallable implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            // 产生随机数
            int num = new Random().nextInt(10);
            System.out.println(String.format("线程:%s,生产了随机数:%d",
                    Thread.currentThread().getName(), num));
            return num;
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1.创建 Callable 子对象
        MyCallable callable = new MyCallable();
        // 2.使用 FutrueTask 接收 Callable
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        // 3.创建线程并设置任务
        Thread thread = new Thread(futureTask);
        // 执行线程
        thread.start();
        // 得到线程的执行结果
        int num = futureTask.get();
        System.out.println("线程返回结果:" + num);
    }
}

(3)线程休眠(sleep)

在这里插入图片描述

(4)创建多少线程合适?

看实际情况,任务分为两种:
1.计算密集型任务;(线程的数量=CPU核数最好)
2.读写文件;(理论上讲线程数越多越好)

2.Thread 类及常见方法

(1)Thread 的常见构造方法

在这里插入图片描述

(2)Thread 的几个常见属性

在这里插入图片描述

  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况,下面我们会进一步说明
  • 优先级高的线程理论上来说更容易被调度到
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行
  • 是否存活,即简单的理解,为 run 方法是否运行结束了
  • 线程的中断问题,下面我们进一步说明

(3)面试题:start() 和 run()

  • 1.run()方法是一个对象的普通方法,它使用的是主线程来执行任务的。
  • 2.start()是线程的开启方法,它使用新的线程来执行任务的。
  • 3.start()方法只能执行一次,而run()可以调用n次。

(4)线程中断的方式

1.自定义全局标识来实现中断;
在这里插入图片描述2.使用Thread的interrupated()方法来中断。
在这里插入图片描述注意:使用系统的Interrupated() 可以及时的终止线程,而使用自定义全局变量终止线程的方式,比较温柔不能在里面终止。

(5)判断线程终止的方式

在这里插入图片描述

3.线程的状态

(1)线程的所有状态

在这里插入图片描述

(2)线程的状态和转移

在这里插入图片描述

注意: 线程常用方法:yield()[用来让出CPU的执行权]
yield分配执行权不一定成功,要看CPU的最终选择,但总体来说还是基本符合预期的。

4.线程不安全的因素

  • 1.CPU是抢占式执行的(万恶之源)
  • 2.多个线程同时操作一个变量
  • 3.内存不可见。
  • 4.原子性
  • 5.指令重排序
  • 6.编译器优化(编译器优化在复杂的多线程中会出现混乱,从而导致线程不安全的问题。)

非线程安全:使用多线程执行任务,最终得到的结果和预期不一样。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秃头小宝儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值