juc概述

1.什么是进程和线程

        进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程,进程--资源分配的最小单位

        线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程--程序执行的最小单位

        进程和线程对比:进程基本上相互独立的,而线程存在于进程内,是进程的一个子集

                                     进程拥有共享的资源,如内存空间等,供其内部的线程共享

                                     进程间通信较为复杂

                                     线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量

                                     线程更轻量,线程上下文切换成本一般上要比进程上下文切换低

      

2.线程的状态

        线程有五种状态(基于操作系统):新建--就绪--运行--阻塞-死亡

 

                                新建:一旦创建了线程对象就处于新建状态

                                就绪:一旦调用了start()方法就处于就绪状态,至于何时处于运行状态,要取                                             决于cpu

                                运行:当前线程获得了cpu即处于运行状态

                                阻塞:当前线程调用了sleep方法,在等待通知,想要获得同步监视器,IO阻塞、suspend()方法调用了

                                死亡:Error或Exception/run()/call()执行完成

        线程有六种状态(基于JavaAPI):新建--运行中(就绪,运行,阻塞)--死亡

        

 

                                新建: 一旦创建了线程对象就处于新建状态

                                运行中:运行中包括了操作系统种的三种状态,就绪--运行--阻塞

                                阻塞:javaAPI中的阻塞分为Blocked,Waiting,Time-Waiting

                                死亡:Error或Exception/run()/call()执行完成

3.线程创建的三种方式(在这里都用匿名内部类的方式实现)

  1.        继承Thread类
       new Thread("线程一"){
                @Override
                public void run() {
                    System.out.println("你好!");
                }
            }.start();

  2.        实现Runnable接口
      new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        log.debug("线程一正在running");
                        // System.out.println("线程一正在running");
                    }
                }
            },"线程一").start();

  3.        实现Callable接口(这里需要使用FutureTask来接收call()方法的返回值)
    FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    return 1;
                }
            });
            Thread thread = new Thread(futureTask, "线程一");
            thread.start();
            Integer integer = futureTask.get();
            System.out.println(integer);

4.线程运行之原理

        栈与栈帧:        我们都知道java虚拟机是由栈、堆、方法区组成,那么栈内存是给谁用的呢,是给线程用的,每个线程启动后,Java虚拟机就会为其分配一个栈内存,每个栈由多个栈帧组成,对应着每次方法调用时所占的内存,每个线程只能有一个活动栈帧,对应着正在执行的那个方法

        线程上下文切换:当发生如下情况时会导致线程上下文切换(即CPU不执行当前线程,转而执行另一个线程)

                                        线程的时间片用完

                                        垃圾回收(停掉所有用户线程,转而由执行垃圾回收任务的那个线程执行)

                                        有更高优先级的线程需要执行

                                        线程自己调用了sleep,yield,join,wait,park,synchronized,lock等方法

                                需要注意的是频繁的上下文切换会影响性能,原因如下:当发生频繁的上下文切换时,需要操作系统保存当前线程的状态,恢复另一个线程的状态,java中对应的概念就是程序计数器(它的作用是记住下一条jvm指令的执行地址),它是线程私有的。状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等

5.常用方法

       start()

       功能说明:启动一个新线 程,在新的线程运行run 方法中的代码

       注意:start 方法只是让线程进入就绪,里面代码不一定立刻 运行(CPU 的时间片还没分给它)。每个线程对象的 start方法只能调用一次,如果调用了多次会出IllegalThreadStateException

        run()

       功能说明:新线程启动后会调用的方法

        注意:如果在构造 Thread 对象时传递了 Runnable 参数,则 线程启动后会调用 Runnable 中的 run 方法,否则默 认不执行任何操作。但可以创建 Thread 的子类对象,来覆盖默认行为

        join()

        功能说明:等待线程运行结 束

        join(long n)

        功能说明:等待线程运行结 束,最多等待 n 毫秒

        getId()

        功能说明:获取线程长整型 的 id

        注意:id 唯一

        getName()

        功能说明:获取线程名

        setName(String)

        功能说明:获取线程名

        getPriority()

        功能说明:获取线程优先级

        setPriority(int)

        功能说明:修改线程优先级

        注意:java中规定线程优先级是1~10 的整数,较大的优先级能提高该线程被CPU调度的机率

        getState()

        功能说明:获取线程状态

        注意:Java 中线程状态是用 6 个 enum 表示,分别为:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED

        isInterrupted()

        功能说明:判断是否被打 断

        注意:不会清除 打断标记

        isAlive()

        功能说明:线程是否存活 (还没有运行完 毕)

        interrupt()

        功能说明:打断线程

        注意:如果被打断线程正在 sleep,wait,join 会导致被打断 的线程抛InterruptedException,并清除 打断标 记 ;如果打断的正在运行的线程,则会设置 打断标 记 ;park 的线程被打断,也会设置 打断标记

        interrupted()

        功能说明:判断当前线程是 否被打断

        注意:会清除打断标记

        currentThread()

        功能说明:获取当前正在执行的线程

        sleep(long n)

        功能说明:让当前执行的线 程休眠n毫秒,休眠时让出cpu的时间片给其它线程

        yield()

        功能说明:提示线程调度器 让出当前线程对 CPU的使用

        注意:主要是为了测试和调试

6.方法区别

        run()和start()方法

               调用直接调用run方法不会启动线程,是在主线程中执行了run方法,需要调用start方法才会启动线程并执行run方法中的代码

        sleep()和yield()方法

                        sleep()方法

                调用sleep()方法会让当前线程从RUNNING状态变为TIME WAITING状态(阻塞)

                其他线程可以调用interrupte()方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException

                睡眠结束后的线程未必会立刻得到执行

                使用TimeUnit代替Thread的sleep可以拥有更好的可读性

                        yield()方法

                调用yield方法会让当前线程从RUNNING状态变为Runnable就绪状态,然后调度执行其他程序

                具体的实现有赖于操作系统的任务调度器

7.线程优先级

        线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它

        如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用

8.同步和异步

        需要等待结果返回,才能继续运行就是同步

        不需要等待结果返回,就能继续运行就是异步

9.不推荐的方法

        还有一些不推荐使用的方法,这些方法已过时,容易破坏同步代码块,造成线程死锁

         stop() 停止线程运行

        suspend() 挂起(暂停)线程运行

        resume() 恢复线程运行

         

        

        

        

        

        

        

        

                                        

        

3.wait和sleep

        1.wait属于Thread类,而sleep属于Object,故每个对象都可以调用sleep方法

        2.wait会释放锁,而sleep不会释放锁

        3.都可以被interrupted方法中断

4.并发和并行

        并发:指的是多个线程竞争同一个资源,多个线程对一个点

        并行:多项工作一起执行,之后再汇总,多个线程对多个点

        结论:单核 cpu 下,多线程不能实际提高程序运行效率,只是为了能够在不同的任务之间切换,不同线程轮流使用 cpu ,不至于一个线程总占用 cpu,别的线程没法干活

                  多核 cpu 可以并行跑多个线程,但能否提高程序运行效率还是要分情况的

                  IO 操作不占用 cpu,只是我们一般拷贝文件使用的是【阻塞 IO】,这时相当于线程虽然不用 cpu,但需要一 直等待 IO 结束,没能充分利用线程。所以才有后面的【非阻塞 IO】和【异步 IO】优化

5.管程

        管程在操作系统中被称为监视器,在Java中被称为锁

        是一种同步机制,保证同一个时间,只有一个线程访问被保护数据或代码

6.用户线程和守护线程

        用户线程:自定义线程,自己通过继承Thread类,实现Runnable接口,实现Callable接口等都是用户线程

        守护线程:即垃圾回收线程

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值