JavaEE初阶----多线程初阶----Thread

本文章为 javaEE初阶 教学

下一篇文章为:面试八股文,多线程进阶!点击这里进行跳转

通过此文章可以学习到:

1、计算机是如何工作的

2、什么是操作系统

3、什么是进程

4、操作系统如何管理进程

5、什么是PCB

6、PCB中的一些属性

7、什么是线程

8、线程和进程的区别

9、java中的Thread类用法


文章目录:

1、了解什么是API

2、关于操作系统

3、进程(跑起来的程序)

4、操作系统如何管理进程

5、PCB中的一些属性

6、进程的调度与隔离性

7、线程

8、经典面试题(线程和进程的区别)

9、Java中的 Thread 类

10、线程的状态

11、线程安全

12、什么是可重入

13、标准库

14、针对于内存可见性的另外一种解释

15、缓存

16、volatile 和 synchronized区别(仅针对于java)

17、wait 和 notify

18、线程安全的单例模型

19、阻塞队列实现—生产者消费者模型

20、定时器的模拟实现

21、线程池的模拟实现


1、了解什么是API

在这里插入图片描述

2、关于操作系统

在这里插入图片描述

3、进程(跑起来的程序)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、操作系统如何管理进程

操作系统管理进程大体分为两部分:

  • 1、先描述一个进程
  • 2、再组织若干个进程(使用一些数据结构,把很多描述进程的信息放到一起,方便进行增删改查)
    在这里插入图片描述

5、PCB的一些属性

①、pid(进程的身份标识)

在这里插入图片描述

②、内存指针(指明即将执行的代码和指令在内存的哪里,以及这个进程执行中依赖的数据的位置)

在这里插入图片描述

那问题来了为什么需要这样一个内存指针

在这里插入图片描述

③、文件描述符表(程序的运行和文件息息相关)

在这里插入图片描述

上述PCB属性:

在这里插入图片描述

所谓进程调度:

在这里插入图片描述

例如:

在这里插入图片描述

这就是所谓的进程调度

在理解下面一组属性我们先需要了解一组知识:并发和并行

在这里插入图片描述

下面正式介绍PCB的下一组属性

通过一个小故事我们来理解一下这四个属性

在这里插入图片描述

①、状态

在这里插入图片描述
在这里插入图片描述

②、优先级

在这里插入图片描述

在这里插入图片描述

③、记账信息

在这里插入图片描述
在这里插入图片描述

④、上下文

在这里插入图片描述
在这里插入图片描述

通过这个例子我们就可以清楚的理解这四个PCB的属性了

在这里插入图片描述

6、进程的调度与隔离性

在这里插入图片描述

这里的知识我们再举个例子:

在这里插入图片描述
在这里插入图片描述

7、线程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8、经典面试题:线程与进程的区别

  • 1、进程包括线程,一个进程可以有一个或多个线程
  • 2、进程和线程是为了处理并发编程这样的场景,但是进程创建和销毁的开销较大,效率较低,相比之下,进程更加轻量,创建和销毁的效率更高(轻量是因为少了申请释放的过程)
  • 3、操作系统创建进程,要给进程分配资源,进程是操作系统分配资源的基本单位,操作系统创建线程,是要在CPU上调度执行的,线程是操作系统调度执行的基本单位
  • 4、进程具有独立性,每个进程有独自的虚拟地址空间,一个进程挂了,一般不会影响到其他进程,同一个进程中的多个线程,由于是公用一个内存空间,一个线程挂了,甚至导致整个进程崩溃
    在这里插入图片描述

9、Java中的 Thread 类

Thread类是什么?

在这里插入图片描述

9.1、五种创建方法

①、创建子类,继承于Thread

class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println("这是一个线程");
    }
}
public class Test {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

②、创建一个类实现Runable接口再创建实例传给Thread类

class MyRunable implements Runnable{
    @Override
    public void run() {
        System.out.println("这是一个线程");
    }
}
public class Test {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunable());
        t.start();
    }
}

在这里插入图片描述

③、使用匿名内部类,简化方法1

public class Test {
    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run() {
                System.out.println("这是一个线程");
            }
        };
        t.start();
    }
}

在这里插入图片描述

④、使用匿名内部类,简化方法2

public class Test {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("这是一个线程");
            }
        });
        t.start();
    }
}

在这里插入图片描述

⑤、使用lambda表达式进一步简化

public class Test {
    public static void main(String[] args) {
       Thread t = new Thread(()-> System.out.println("这是一个线程"));
       t.start();
    }
}

在这里插入图片描述

9.2、多线程的作用

先看一个串行的代码:

在这里插入图片描述

虽然通过上述的代码可以发现执行效率显著提升,但也要注意一个问题;

在这里插入图片描述

9.3、其他属性和方法

①、为线程起别名

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

②、是否后台进程

在这里插入图片描述
在这里插入图片描述

上述代码的t1,t2都是前台进程:

在这里插入图片描述

③、是否存活

在这里插入图片描述
在这里插入图片描述

9.4、Thread中的一些方法

9.4.1、run方法

在这里插入图片描述

9.4.2、中断线程

①、手动设置标志位

在这里插入图片描述

②、使用线程中的方法设置标志位
public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
           while(!Thread.currentThread().isInterrupted()){
               System.out.println("hello thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        t.start();
        Thread.sleep(5000);
        t.interrupt();
    }
}

在这里插入图片描述

public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(()->{
           while(!Thread.currentThread().isInterrupted()){
               System.out.println("hello thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
                   break;
               }
           }
        });
        t.start();
        Thread.sleep(5000);
        t.interrupt();
    }
}

在这里插入图片描述

9.4.3、线程等待

两个版本:一个-----线程等待没有时间限制(死等)

在这里插入图片描述

另外一个版本:有时间限制

在这里插入图片描述

在这里插入图片描述

9.4.4、获取当前线程的名字

在这里插入图片描述

9.4.5、线程休眠

在这里插入图片描述


10、线程的状态

10.1、NEW

在这里插入图片描述

10.2、TERMINATED

在这里插入图片描述

10.3、RUNNABLE

在这里插入图片描述

10.4、TIME_WAITING

在这里插入图片描述

10.5、BLOCK

在这里插入图片描述

10.6、WAITING

在这里插入图片描述

总结:

在这里插入图片描述


11、线程安全

在这里插入图片描述


11.1、什么情况下认为线程是安全的

在这里插入图片描述


11.2、一个线程不安全的典型案例

在这里插入图片描述


11.3、如何解决线程安全问题

在这里插入图片描述


11.4、产生线程不安全的原因

在这里插入图片描述


11.5、synchronized的用法

在这里插入图片描述

总结上述知识:

在这里插入图片描述
在这里插入图片描述


12、可重入

在这里插入图片描述


12.1、什么是死锁

在这里插入图片描述

这样的问题就是死锁

所以在设计synchronized的时候:

在这里插入图片描述
在这里插入图片描述


12.2、死锁的其他使用从场景

在这里插入图片描述


12.3、死锁的四种必要条件

在这里插入图片描述


13、标准库

在这里插入图片描述


14、针对于内存可见性的另外一种解释

在这里插入图片描述


15、缓存

在这里插入图片描述


16、volatile和synchronized区别(仅针对于java)

在这里插入图片描述


17、wait 和 notify

在这里插入图片描述
在这里插入图片描述


18、单例模型

预备知识:

在这里插入图片描述

18.1、饿汉模型

在这里插入图片描述

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2022-03-31
 * Time: 9:29
 */
//线程安全的单例模型
    //1、饿汉模型
class Singleton{
    private static Singleton instance = new Singleton();

    private Singleton(){};

    public static Singleton getInstance() {
        return instance;
    }
}
public class Demo {
    public static void main(String[] args) {
        Singleton instane = Singleton.getInstance();
    }
}


18.2、懒汉模型

在这里插入图片描述

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2022-03-31
 * Time: 9:31
 */
//线程安全的单例模型 懒汉模型
class Singleton2{
    private volatile static Singleton2 instance = null;

    private Singleton2(){};

    public static Singleton2 getInstance() {
        if(instance == null){
            synchronized (Singleton2.class){
                if(instance == null){
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Singleton2 instance = Singleton2.getInstance();
    }
}


19、阻塞队列实现—生产者消费者模型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2022-03-31
 * Time: 9:34
 */
//通过阻塞队列实现生产者消费者模型
class MyBlockingQueue{
    private int[] data = new int[1000];
    private int head = 0;
    private int tail = 0;
    private int size = 0;

    private Object locker = new Object();

    public void put(int val) throws InterruptedException {
        synchronized (locker){
            if(size == data.length){
                locker.wait();
            }

            data[tail] = val;
            tail++;
            if(tail >= data.length){
                tail = 0;
            }

            size++;
            locker.notify();
        }
    }

    public Integer take() throws InterruptedException {
        synchronized (locker){
            if(size == 0){
                locker.wait();
            }

            int ret = data[head];
            head++;

            if(head >= data.length){
                head = 0;
            }

            size--;
            locker.notify();
            return ret;
        }
    }
}
public class Demo3 {
    public static void main(String[] args) {
        MyBlockingQueue qu = new MyBlockingQueue();
        Thread produce = new Thread(()->{
            int num = 0;
            while(true){
                System.out.println("生产了:"+num);
                try {
                    qu.put(num);
                    num++;
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        produce.start();

        Thread consumer = new Thread(()->{
           while(true){
               try {
                   int num = qu.take();
                   System.out.println("消费了:"+num);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        consumer.start();
    }
}


20、模拟实现定时器

在这里插入图片描述

import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2022-03-31
 * Time: 10:09
 */
//先描述一个任务
class MyTask{
    //任务具体是什么
    private Runnable runnable;

    //任务完成的具体时间
    private long time;

    //给任务初始化
    public MyTask(Runnable runnable,long delay){
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }
    //执行任务
    public void run(){
        runnable.run();
    }

    public long getTime() {
        return time;
    }
}

//组织这些任务
class MyTimer {

    //使用带有优先级的阻塞队列
    PriorityBlockingQueue<MyTask> qu = new PriorityBlockingQueue<>(10, new Comparator<MyTask>() {
        @Override
        public int compare(MyTask o1, MyTask o2) {
            return (int) (o1.getTime() - o2.getTime());
        }
    });

    //把任务放到阻塞队列中
    public void schedule(Runnable runnable, long delay) {
        MyTask myTask = new MyTask(runnable, delay);
        //这里成功放一个元素就通知一下
        qu.put(myTask);
        synchronized (locker) {
            locker.notify();
        }
    }

    private Object locker = new Object();
    //创建一个扫描贤臣去寻找先执行的任务
    public MyTimer(){
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    MyTask myTask = qu.take();
                    long curTime = System.currentTimeMillis();
                    //这里会造成忙等
                    if (curTime < myTask.getTime()) {
                        qu.put(myTask);
                        //等待差值的时间
                        synchronized (locker) {
                            locker.wait(myTask.getTime() - curTime);
                        }
                    } else {
                        myTask.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
    }
}
public class Demo4 {
    public static void main(String[] args) {
        MyTimer myTime = new MyTimer();
        myTime.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello timer");
            }
        },3000);
        System.out.println("main");
    }
}



21、模拟实现线程池

在这里插入图片描述

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Lenovo
 * Date: 2022-03-31
 * Time: 10:18
 */

//模拟实现线程池
class MyThreadPool{
    //创建任务并使用阻塞队列组织任务
    private BlockingQueue<Runnable> qu = new LinkedBlockingQueue<>();

    //创建一个工作类线程
    static class Worker extends Thread{
        private BlockingQueue<Runnable> qu = null;

        public Worker(BlockingQueue<Runnable> qu){
            this.qu = qu;
        }

        public void run(){
            while(true){
                //从阻塞队列中取出来一个任务执行
                try {
                    Runnable runnable = qu.take();
                    runnable.run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //把执行好的线程组织在顺序表中
    List<Thread> workers = new ArrayList<>();
    public MyThreadPool(int n){
        for (int i = 0; i < n; i++) {
            Worker worker = new Worker(qu);
            worker.start();
            workers.add(worker);
        }
    }

    //把任务提交到阻塞队列中
    public void submit(Runnable runnable) throws InterruptedException {
        qu.put(runnable);
    }

}
public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool pool = new MyThreadPool(10);
        for (int i = 0; i < 100; i++) {
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello pool");
                }
            });
        }
    }
}

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦の澜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值