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 类

  • 9.1、五种创建方法
  • 9.2、多线程的作用
  • 9.3、其他属性和方法
  • 9.4.、java中的一些重要的方法
  • 9.4.1、run方法
  • 9.4.2、中断线程
  • 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、什么是死锁
  • 12.2、死锁的其他场景
  • 12.3、死锁的四个条件

13、标准库

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

15、缓存

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

17、wait 和 notify

18、线程安全的单例模型

  • 18.1、饿汉模型
  • 18.2、懒汉模型

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

20、定时器的模拟实现

21、线程池的模拟实现


1、了解什么是API

JavaEE初阶----多线程初阶----Thread_第1张图片

2、关于操作系统

JavaEE初阶----多线程初阶----Thread_第2张图片

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

JavaEE初阶----多线程初阶----Thread_第3张图片
JavaEE初阶----多线程初阶----Thread_第4张图片
JavaEE初阶----多线程初阶----Thread_第5张图片

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

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

  • 1、先描述一个进程
  • 2、再组织若干个进程(使用一些数据结构,把很多描述进程的信息放到一起,方便进行增删改查)
    JavaEE初阶----多线程初阶----Thread_第6张图片

5、PCB的一些属性

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

JavaEE初阶----多线程初阶----Thread_第7张图片

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

JavaEE初阶----多线程初阶----Thread_第8张图片

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

JavaEE初阶----多线程初阶----Thread_第9张图片

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

JavaEE初阶----多线程初阶----Thread_第10张图片

上述PCB属性:

在这里插入图片描述

所谓进程调度:

JavaEE初阶----多线程初阶----Thread_第11张图片

例如:

JavaEE初阶----多线程初阶----Thread_第12张图片

这就是所谓的进程调度

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

JavaEE初阶----多线程初阶----Thread_第13张图片

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

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

JavaEE初阶----多线程初阶----Thread_第14张图片

①、状态

JavaEE初阶----多线程初阶----Thread_第15张图片
JavaEE初阶----多线程初阶----Thread_第16张图片

②、优先级

JavaEE初阶----多线程初阶----Thread_第17张图片

JavaEE初阶----多线程初阶----Thread_第18张图片

③、记账信息

JavaEE初阶----多线程初阶----Thread_第19张图片
JavaEE初阶----多线程初阶----Thread_第20张图片

④、上下文

JavaEE初阶----多线程初阶----Thread_第21张图片
JavaEE初阶----多线程初阶----Thread_第22张图片

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

JavaEE初阶----多线程初阶----Thread_第23张图片

6、进程的调度与隔离性

JavaEE初阶----多线程初阶----Thread_第24张图片

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

JavaEE初阶----多线程初阶----Thread_第25张图片
JavaEE初阶----多线程初阶----Thread_第26张图片

7、线程

JavaEE初阶----多线程初阶----Thread_第27张图片
JavaEE初阶----多线程初阶----Thread_第28张图片
JavaEE初阶----多线程初阶----Thread_第29张图片

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

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

9、Java中的 Thread 类

Thread类是什么?

JavaEE初阶----多线程初阶----Thread_第31张图片

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();
    }
}

JavaEE初阶----多线程初阶----Thread_第32张图片
JavaEE初阶----多线程初阶----Thread_第33张图片
JavaEE初阶----多线程初阶----Thread_第34张图片

②、创建一个类实现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();
    }
}

JavaEE初阶----多线程初阶----Thread_第35张图片

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

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

JavaEE初阶----多线程初阶----Thread_第36张图片

④、使用匿名内部类,简化方法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();
    }
}

JavaEE初阶----多线程初阶----Thread_第37张图片

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

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

JavaEE初阶----多线程初阶----Thread_第38张图片

9.2、多线程的作用

先看一个串行的代码:

JavaEE初阶----多线程初阶----Thread_第39张图片

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

JavaEE初阶----多线程初阶----Thread_第40张图片

9.3、其他属性和方法

①、为线程起别名

JavaEE初阶----多线程初阶----Thread_第41张图片

JavaEE初阶----多线程初阶----Thread_第42张图片
JavaEE初阶----多线程初阶----Thread_第43张图片

②、是否后台进程

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

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

JavaEE初阶----多线程初阶----Thread_第44张图片

③、是否存活

JavaEE初阶----多线程初阶----Thread_第45张图片
JavaEE初阶----多线程初阶----Thread_第46张图片

9.4、Thread中的一些方法

9.4.1、run方法

JavaEE初阶----多线程初阶----Thread_第47张图片

9.4.2、中断线程

①、手动设置标志位

JavaEE初阶----多线程初阶----Thread_第48张图片

②、使用线程中的方法设置标志位

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();
    }
}

JavaEE初阶----多线程初阶----Thread_第49张图片

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();
    }
}

JavaEE初阶----多线程初阶----Thread_第50张图片

9.4.3、线程等待

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

JavaEE初阶----多线程初阶----Thread_第51张图片

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

JavaEE初阶----多线程初阶----Thread_第52张图片

JavaEE初阶----多线程初阶----Thread_第53张图片

9.4.4、获取当前线程的名字

JavaEE初阶----多线程初阶----Thread_第54张图片

9.4.5、线程休眠

JavaEE初阶----多线程初阶----Thread_第55张图片


10、线程的状态

10.1、NEW

JavaEE初阶----多线程初阶----Thread_第56张图片

10.2、TERMINATED

JavaEE初阶----多线程初阶----Thread_第57张图片

10.3、RUNNABLE

JavaEE初阶----多线程初阶----Thread_第58张图片

10.4、TIME_WAITING

JavaEE初阶----多线程初阶----Thread_第59张图片

10.5、BLOCK

JavaEE初阶----多线程初阶----Thread_第60张图片

10.6、WAITING

JavaEE初阶----多线程初阶----Thread_第61张图片

总结:

JavaEE初阶----多线程初阶----Thread_第62张图片


11、线程安全

JavaEE初阶----多线程初阶----Thread_第63张图片


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

JavaEE初阶----多线程初阶----Thread_第64张图片


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


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

JavaEE初阶----多线程初阶----Thread_第65张图片


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


11.5、synchronized的用法

JavaEE初阶----多线程初阶----Thread_第66张图片

总结上述知识:

JavaEE初阶----多线程初阶----Thread_第67张图片
JavaEE初阶----多线程初阶----Thread_第68张图片


12、可重入

在这里插入图片描述


12.1、什么是死锁

JavaEE初阶----多线程初阶----Thread_第69张图片

这样的问题就是死锁

所以在设计synchronized的时候:

JavaEE初阶----多线程初阶----Thread_第70张图片
JavaEE初阶----多线程初阶----Thread_第71张图片


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

JavaEE初阶----多线程初阶----Thread_第72张图片


12.3、死锁的四种必要条件

JavaEE初阶----多线程初阶----Thread_第73张图片


13、标准库

JavaEE初阶----多线程初阶----Thread_第74张图片


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

JavaEE初阶----多线程初阶----Thread_第75张图片


15、缓存

JavaEE初阶----多线程初阶----Thread_第76张图片


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

JavaEE初阶----多线程初阶----Thread_第77张图片


17、wait 和 notify

JavaEE初阶----多线程初阶----Thread_第78张图片
JavaEE初阶----多线程初阶----Thread_第79张图片


18、单例模型

预备知识:

JavaEE初阶----多线程初阶----Thread_第80张图片

18.1、饿汉模型

JavaEE初阶----多线程初阶----Thread_第81张图片

/**
 * 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、阻塞队列实现—生产者消费者模型

JavaEE初阶----多线程初阶----Thread_第82张图片
JavaEE初阶----多线程初阶----Thread_第83张图片
JavaEE初阶----多线程初阶----Thread_第84张图片
JavaEE初阶----多线程初阶----Thread_第85张图片

/**
 * 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、模拟实现线程池

JavaEE初阶----多线程初阶----Thread_第86张图片

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");
                }
            });
        }
    }
}

你可能感兴趣的:(JavaEE,java,数据结构,算法,JavaEE,多线程)