并发编程---线程与进程

发布于:2024-10-12 ⋅ 阅读:(7) ⋅ 点赞:(0)

业务场景:小明去理发店理发。

小明去理发店理发,完成理发需要吹,剪,洗、理的过程。由这个场景我们引用进程和线程这两个

概念。

一.进程

1.什么是进程

进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位。进程是可与其他程序并发执行的程序,在一个数据集合上的运行过程。它是系统进行资源分配和调度的一个独立单位。

大家打开windows的任务管理器就可以看到,系统运行的进程。

2.进程的几个概念

2.1 结构性

为了控制和管理进程,系统为每个进程设立一个**进程控制块\- PCB。

每个进程拥有一个控制块(PCB),这是进程存在的依据,用于描述和记录进程的动态变化过程,并使之能正确运行。

2.2 动态性

进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的,进程在其生命周期内,在三种基本状态(产生、执行、消亡)之间转换。

进程是程序在处理机上的一次动态执行过程。它因创建而产生,由调度而执行,因得不到资源而暂停执行,最后因撤销而消亡。

2.3 异步性

由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。

系统中的各进程以独立的、不可预知的速度向前推进。

2.4 并发性

任何进程都可以同其他进程一起向前推进。

多个进程实体可以同时存在于内存中,在一段时间内都得到运行,它们在执行时间上是重叠的。

2.5 独立性

进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。

进程是能独立运行的基本单位,也是系统进行资源分配和调度的独立单位。

二.线程

我们把理发这个进程分解为几个子任务(线程)如下:

1.线程的定义

 1.1 线程是程序执行的**最小单位\,而进程是操作系统分配资源的最小单位;

 1.2 一个进程由一个或多个线程组成,线程是一个进程中代码的**不同执行路线\;

 1.3 进程之间相互独立,但同一进程下的**各个线程之间共享程序的内存空间(包括代码段,数据     集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;

 1.4 调度和切换:线程上下文切换比进程**上下文切换要快得多\;

2.线程和进程的区别

3.线程的切换方式

三.线程的生命周期

1.线程创建

1.1 继承Thread类

public class ThreadDemo extends Thread{
    public ThreadDemo(String name){
        setName(name);
    }
    public void run(){
        for (int i = 1;i <= 100;i++){
            System.out.println(getName() + ":" + i);
            if (i==5) throw new RuntimeException("死亡");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new ThreadDemo("A");
        Thread t2 = new ThreadDemo("B");
        t2.start();//ready
        t1.start();//ready
//        Thread.sleep(100);
//        System.out.println("main");
    }
}

1.2 实现Runnable接口

/**
 * 实现Runnable接口
 */
public class ThreadDemo02 implements Runnable{
    private String name;

    public ThreadDemo02(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        for (int i = 0;i < 10;i++){
            System.out.println(this.name + "---" + i);
        }
    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new ThreadDemo02("A"));
        Thread t2 = new Thread(new ThreadDemo02("B"));

        t2.start();
        t1.start();
    }
}

1.3 实现Callable接口

public class ThreadDemo01 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i < 1000; i++) {
            sum += i;
        }
        return sum;
}
public static void main(String[] args) throws Exception {
        FutureTask<Integer> ft =
         new FutureTask<Integer>(new ThreadDemo01());
        ft.run();
        System.*out\*.println("s:" + ft.get());
    }
}

2.线程就绪

Thread t = new Thread( );
t.start( ); //启动线程(线程就绪)

3.线程运行

一旦CPU分配了运行时间,就调用线程的run( )方法。

4.线程阻塞

线程阻塞可以分为以下几种类型:

1‌‌.等待阻塞‌:线程调用wait()方法,进入等待状态,等待其他线程的通知或者中断。
‌‌2.同步阻塞‌:线程在获取对象锁时,如果该锁被其他线程占用,则进入同步阻塞状态。
‌‌3.睡眠阻塞‌:线程调用sleep()方法,进入睡眠状态,等待一定时间后自动唤醒。
‌‌4.IO阻塞‌:线程在执行IO操作时,如果IO操作没有完成,则进入IO阻塞状态。
‌5.其他阻塞‌:线程调用join()方法等待其他线程执行完毕,或者调用yield()方法主动让出CPU资源。

5.线程死亡

线程死亡是线程生命周期的一个重要阶段。线程在完成其任务后自动进入死亡状态。当一个线程完成其执行,或因未捕获的异常而退出时,该线程将进入死亡状态,此时线程的所有资源将被释放。

线程死亡的条件:
1.正常结束:线程执行完run()方法。
2.异常结束:在线程执行过程中出现未处理的异常。
3.被强制终止:其他线程调用stop()等方法。

四.守护线程与用户线程

1.用户线程User Thread(创建的线程)

不需要内核支持而在用户程序中实现的线程

用户线程指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。

2.守护线程Daemon Thread(守护最后一个用户线程才结束)

守护线程是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 守护线程
 */
public class ShouHuDemo {
    public static void main(String[] args) throws Exception{
        Thread t1 = new Thread(() -> {
            while (true){
                try {
                    Date now = new Date();
                    long s1 = now.getTime();

                    SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd hh:mm:ss");
                    Date parse = sdf.parse("24-09-15 17:15:00");
                    System.out.println(sdf.format(now));

                    long s2 = parse.getTime();
                    System.out.println("s1:" + s1 + "s2:" + s2);

                    if (s1 == s2){
                        System.out.println("到点了!!!");
                    }

                    Thread.sleep(1000);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0;i < 100;i++){
                try {
                    System.out.println("o" + i);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        t1.setDaemon(true);
        t1.start();
        t2.start();

    }
}