Thread

程序:为解决某种问题,使用计算机语言编写的一系列指令的集合。

         本章中的程序,特指的是静态的,安装在硬盘上代码集合。

进程:运行中的程序(被加载到内存中),是操作系统进行资源分配的最小单位

线程:进程可以进一步细化为线程,是进程内一个最小的执行单元,是cpu进行任务调度的最小单位。

运行中的qq就是一个进程,操作系统会为这个进程分配内存资源,一个聊天窗口就认为是一个线程,这多个聊天窗口可以同时被cpu执行,但是这些聊天窗口属于进程,线程是属于进程。

早期没有线程,早期cpu执行的时候,是以进程为单位执行,进程单位还是比较大的,当一个进程运行时,其他的进程就不能执行,所以后来,将进程中的多个任务,细化为线程,cpu执行单位,也从进程转为更小的线程

进程和线程的关系

        一个进程中可以包含多个线程

        一个线程只能隶属于一个进程,线程不能脱离进程存在

        一个进程中至少有一个线程(即主线程)Java中的main方法,就是用来启动主线程

        在主线程中可以创建并启动其他线程

        所有线程都共享进程内存资源

需求:想在Java程序中有几件不相关的事情同时有机会执行

可以在Java中创建线程,把一些要执行的任务放在线程中执行,

这样的话,都拥有让cpu执行的权利

在Java中创建线程

        创建线程方式1:

                继承Thread类的方式,重写run()

                创建自己定义的线程类对象,调用start()启动线程

                MyThread  extends  Thread{

                }

        创建线程方式2:

        类  实现Runnable接口,把这个类不能称为线程,是一个任务类

        重写run()

        new Thread(任务对象);

        调用线程对象的start(),启动线程

以后用第二种更多一些:

        1.避免了单继承的局限性,因为Java是单继承的,继承了Thread类,就不能继承其他类

        2.更适合多线程共享同一份资源的场景

Thread类常用的方法

        Thread表示线程,提供了很多的方法,来对线程进行控制.

        run();线程要执行的任务

        start();启动Java线程的

        

        构造方法

                new Thread(Runnable runnable);接收一个任务对象

                new Thread(Runnable runnable,String name);接收一个任务对象,并为线程设置名字

                setName("我的线程1");为线程设置名字

                String getName();获得线程的名字

                Thread.currentThread();在任务中获得当前正在执行的线程

                setPriority(int p)设置优先级        1~10之间        默认是5

                getPriority();获得优先级

                sleep(long m);让线程休眠指定时间,ms单位

                join();让其他线程等待当前线程结束

操作系统线程任务调度算法

        先来先服务(FCFS)调度算法

        短作业优先(SJF)调度算法

        优先级调度算法

        时间片轮转调度算法

        高响应比优先调度算法

        多级反馈队列调度算法(集合了前几种算法的优点)

线程声明周期,线程从创建到销毁

期间经历5个阶段

新建new Thread();处于新建状态,此状态还不能被执行

        调用start()启动线程 让线程进入到就绪状态,

就绪

        获得到CPU执行权后,线程进入到CPU执行

运行

        运行中的线程可以被切换,回到就绪状态,也可能因为休眠等原因进入阻塞状态

阻塞

        线程休眠时间到了  回到就绪状态

死亡

        当线程中所有的任务执行完了,线程也就自动销毁

守护线程

        守护线程也是线程中的一种,区别在于它的结束,

        如果一个线程是守护线程,那么他会等Java中其他的线程任务结束后,自动终止

        守护线程是为其他线程提供服务的,例如jvm中的垃圾回收线程,就是一个守护线程

多线程

        在一个应用程序中,存在多个线程,不同的线程可以并行的执行任务

多线程的优点:

        提高程序的处理能力

        杀毒软件  (垃圾清理  病毒查杀  ...)一起处理

多线程的缺点:

        线程也是需要占用内存资源和CPU资源(小意思 可以提升硬件设备)

        多个线程对同一个共享资源进行访问,会出现线程安全问题

        龟兔赛跑中的flag就是共享资源 

如何解决多个线程访问同一个共享资源时不出问题?

        同步 = 排队 + 锁      一次只能有一个线程访问共享资源

        加锁方式1:使用synchroinzed关键字修饰代码块 和 方法

/*
    修饰代码块
        同步对象要求:
            多个线程用到的必须是同一个对象,
            可以是Java中任何类的对象
            作用:用来记录有没有线程进入到同步代码块中
*/
    synchronized(同步对象/锁){
        
        //同步代码块,一次只允许一个线程进入

}

修饰方法:

        1.锁不需要我们提供,会默认提供锁对象

        2.synchronized如果修饰的是非静态的方法,锁对象时this

           synchronized如果修饰的是静态方法,锁对象是类的Class对象

           一个类只有一个Class对象

        加锁方式2:

                使用jdk中提供的ReentrantLock类实现加锁

                ReentrantLock只能对某一段代码块加锁,不能对整个方法加锁

synchronized 和 ReentrantLock区别

相同点:

1.synchronized 是一个关键字,ReentrantLock是一个类

2.synchronized修饰代码块和方法,ReentrantLock只能修饰代码块

3.synchronized可以隐式的加锁和释放锁,运行过程中如出现了异常可以自动释放

ReentrantLock需要手动的添加锁和释放锁,建议在finally代码块中释放锁

线程间的通信(在同步代码块的基础上,使用wait,notify对线程进行控制)

创建线程方式3:实现Callable接口

重写call()方法

call() 可以有返回值,可以抛出异常,还可以自定义返回结果的类型

wait()是Object类中方法,必须在同步代码块中使用,wait()后可以释放锁,必须等待其他线程唤醒

sleep()是Thread类中的方法,在任何地方都可以使用,sleep()不会释放锁,在休眠指定的时间后,就会恢复(阻塞-->就绪)

你可能感兴趣的:(jvm)