进程、线程、多线程

一、线程与进程

一个进程就是一个应用程序,进程包含线程
一个进程至少包含一个线程,大部分都是有多条线程在执行任务
进程是系统资源分配资源的最小单位
线程是进程内部的一个执行任务
线程内多个线程是共享进程资源的,线程资源调度的最小单位

Java程序是否是多线程的吗?

答:Java是多线程的,至少有main线程

二、线程创建【重点】

Thread

创建线程的方式有很多
1. 继承Thread
2. 实现Runnable接口
3. 使用Callable和Future来完成
4. 使用线程池获得线程

2.1继承Thread

  1. 自定义类

  1. 继承Thread类

  1. 重写run方法

  1. 创建子类对象

  1. 调用start方法启动线程

  1. start()方法内部执行时会调用run()方法

2.2实现Runnable接口

  1. 自定义类

  1. 实现Runnable接口

  1. 重写run方法

  1. 创建自实现类对象

  1. 把子实现类对象当构造方法的方法参数来创建Thread对象

  1. 有thread调用start方法开启线程

2.3区别

继承Thread开启线程和实现Runnable接口开启线程的区别?

答:

1.一个继承,一个实现

2.继承Thread后,值集创建对象即可调用start开启线程

3.实现Runnable接口的子类,还需要在创建Thread类对象才开调用start开启线程

4.从使用便捷度来说,继承Thread开启线程会方便一点

5.继承Thread类就限制了该类在继承别的类,因为只能单继承,而实现接口的同时可以继承别的类,并且还允许多继承

所以推荐使用接口来实现(扩展性比较好)

三、线程状态

ps:草图,后续更改完善

四、线程优先级

默认优先级是5,最高是10,最低是1,不能越界

注意:不是一定优先级高的先执行,只是大概率上会是

五、线程名

默认线程名,从Thread-0开始

通过setName设置线程名

eg: thread0.setName("绿皮");

获得线程的名字

System.out.println(Thread.currentThread( ).getName( ));

通过构造方法设置线程名

Thread thread = new Thread("和谐号")

六、线程安全

6.1线程安全:

1、完整的步骤可能会被破坏,(要保证方法执行步骤的完整性)

  1. 线程内的数据可能会被别的线程修改

  • 临界资源:共享资源(同⼀个对象),一次只可以有一个线程操作,才可以保证准确性

  • 原子操作:不可拆分的步骤,被视作一个整体。其步骤不能打乱

6.2线程的安全方式

同步方法 (

给方法加锁,即设置同步锁关键词synchronized

锁对象是当前对象,即this)

同步代码块(

将需要安全的代码块使用同步代码块包裹,设置锁对象

锁可以是任意对象,但是锁必须是同一个锁,才能锁住,保证安全)

其实就是给需要“同步”,需要“安全”,“步骤一致,不能打乱”的代码加锁

6.3sleep和wait

加锁后,sleep"抱着锁睡觉",是说线程休眠不会让出锁,即不会让出资源,其他线程无法执行,等着这个线程休眠结束并且执行完毕。

wait会让出锁,让可以执行、所需资源充足的线程执行。

七、线程通信[熟悉]

7.1 介绍

线程通信,就是线程之间产生联系.

即通知,例如线程A执行到一定时候会停下,同时通知另外的线程B执行,线程B执行到一定时候,也停下,通知线程A执行

以上操作需要Object类的方法

  • wait() 让当前线程等待

  • notify() 唤醒一个(随机一个)处于等待状态的线程

  • notifyAll() 唤醒所有处于等待状态的线程

7.2 两个个线程通信

// 具体哪台打印机执行的标志
    private int flag = 1;

    // 现在使用同步方法,print1和print2方法由同一个对象打印机对象调用
    // print1方法和print2方法锁是同一个,是this,即打印机对象
    public synchronized void print1() {
        if (flag != 1) {
            try {
                // 锁是谁,就用谁调用wait
                // 当前线程就陷入等待,会让出资源释放锁
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace( );
            }
        }
        System.out.print("1 ");
        System.out.print("2 ");
        System.out.print("3 ");
        System.out.print("4 ");
        System.out.print("\r\n");

        // 干完活,修改标志
        flag = 2;

        // 通知另外一个处于等待状态的线程
        // 锁是谁,用谁调用方法
        this.notify();
    }

// print2同print1,flag为2时运行

锁是谁,就用谁调用wait

如果没有加锁,直接调用该方法唤醒线程,会报错IllegalMonitorStateException

锁是谁,用谁调用方法

    // 锁对象
    private Object obj = new Object();

    // 具体哪台打印机执行的标志
    private int flag = 1;

    // 现在使用同步方法,print1和print2方法由同一个对象打印机对象调用
    // print1方法和print2方法锁是同一个,是this,即打印机对象
    public void print1() {
        // 同步代码块,现在锁是字节码文件
        synchronized(Printer.class) {
            if (flag != 1) {
                try {
                    // 锁是谁,就用谁调用wait
                    // 当前线程就陷入等待,会让出资源释放锁
                    // 用字节码锁来调用wait方法
                    Printer.class.wait( );
                } catch (InterruptedException e) {
                    e.printStackTrace( );
                }
            }
            System.out.print("1 ");
            System.out.print("2 ");
            System.out.print("3 ");
            System.out.print("4 ");
            System.out.print("\r\n");

            // 干完活,修改标志
            flag = 2;

            // 通知另外一个处于等待状态的线程
            // 只能唤醒在此对象监视器(加过锁的)上等待的单个线程.
            // 如果没有加锁,直接调用该方法唤醒线程,会报错IllegalMonitorStateException
            // 锁是谁,用谁调用方法
            Printer.class.notify( );

        }
    }

7.5 总结

特殊的:
wait和notify方法需要在同步方法或者同步代码块执行
wait会让当前线程进入等待状态,让出资源,其他线程可以执行
wait和notify()方法谁调用? 当前锁对象是谁,就是谁调用该方法

问 wait和sleep有什么区别?
答:
wait是Object类的方法,sleep是Thread类方法
wait和sleep都可以让当前线程进入阻塞状态
但是wait阻塞当前线程,会让出系统资源,其他线程可执行;但是sleep阻塞当前线程,会持有锁不释放,其他线程无法执行
wait需要在同步方法或同步代码快使用,但是sleep可以在同步或非同步都可以使用

问 为什么wait和notify方法要设计在Object类中?
答: 因为锁可以是任意对象,又因为wait和notify需要被 锁对象调用,那么锁对象是任意的,wait和notify方法也能被任意对象调用,所以就设计在Object类中,因为Object类是所有类的父类

八、 线程池

8.1ThreadPoolExecutor[重要]

ThreadPoolExecutor 很重要,有7个参数

参数名

解释

备注

int corePoolSize

指定线程池的线程数量(核心线程数)

不能小于0

int maximumPoolSize

指定线程池可支持的最大线程数

最大数量>=核心线程数

long keepAliveTime

指定临时线程的最大存活时间

不能小于0

TimeUnit unit

指定存活时间的单位(秒,分,时,天)

时间单位

BlockingQueue<Runnable> workQueue

指定任务队列

ThreadFactory threadFactory

指定哪个线程工厂创建线程

RejectedExecutionHandler handler

指定线程忙,任务队列满的时候新任务来了怎么办?拒绝

问: 什么是创建临时线程?

答: 新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建线程

问:什么时候开始拒绝任务?

答:核心线程和临时线程都在忙,任务队列也满了,新的任务过来就会拒绝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值