juc从入门到入土

一、进程,线程

进程:进程说白了就是一个程序的一个实例,一个程序可以开多个实例,也可以只开一个实例。一个应用打开就是一个进程。有的程序限制了只能开一个实例,比如微信,QQ音乐等,而记事本,浏览器,代码编辑器可以开多个实例。也可以说进程是程序运行的过程。

线程:线程是任务调度的最小单元,进程就是线程的容器,一个进程里可以有多个线程。

进程是负责将指令分配给线程,或者负责将内存分配给线程等工作。

进程或线程的上下文切换:当一个进程没工作则需要将内存分配给别的进程,这就是进程的上下文切换,线程上下文切换也是一样。

二、并发,并行

并发:多个线程轮流使用cpu的时间片叫做并发。

并行:当cpu存在多个核心时,此时多个线程可以同时使用cpu的时间片,这就叫做并行
单核心cpu调度多线程在微观上执行程序是串行的,但在宏观上可以看成并行,但本质还是串行,为什么说在宏观上并行呢?因为cpu的最小的时间片可以为10ms左右,而我们人能分辨出的最小时间为0.1s左右,所以在宏观上单核心cpu调度多线程可以看作并行。

单核心cpu的多线程只有并发,而多核心的多线程既有并发又有并行。

三,同步,异步

在方法调用方角度来说,等待方法执行完返回结果的叫同步,不等待方法执行完返回结果的叫异步。

想要实现异步就必须通过多线程:

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        Thread t1=new Thread(){
            @Override
            public void run(){
                log.debug("计算1到1亿的总和");
            }
        };
        t1.setName("t1");
        t1.start();
        log.debug("计算1+1的总和");
    }
}

执行结果:
22:25:35 [t1] c.Test1 - 计算1到1亿的总和
22:25:35 [main] c.Test1 - 计算1+1的总和

在上面的执行中计算1到1亿的总和的代码在计算1+1的总和的代码之前,但是计算1到1亿的总和所用时间显然比计算1+1的总和的时间长,所以我在想在执行计算1到1亿的总和的时候等待,我想往下执行,这就要用到多线程才能实现异步。

四,多线程

在cpu有多个核心的前提下的多线程相对于单线程可以提高效率,在cpu只有一个核心的前提下多线程相对于单线程会降低效率,因为会有上下文切换的时间。

五,多线程的实现方法

1.直接使用Thread对象

    public static void main(String[] args) {
        //这里只是创建了一个线程对象,并没有把该线程纳入任务调度器管理
        Thread t1=new Thread(){
            @Override
            public void run(){
                log.debug("计算1到1亿的总和");
            }
        };
        t1.setName("t1");
        //将该线程纳入任务调度器管理
        t1.start();
        log.debug("计算1+1的总和");
    }

2.通过Runnable接口

    public static void main(String[] args) {
        Runnable runnable=()->{
            log.debug("running");
        };
        Thread t2=new Thread(runnable);
        t2.start();
        log.debug("running");
    }

3.通过FutureTask对象

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建任务对象
        FutureTask<Integer> futureTask=new FutureTask<>(()->{
            log.debug("running");
            return 100;
        });
        Thread t3=new Thread(futureTask);
        t3.setName("t3");
        t3.start();//开启名为t3的线程,注意是异步的,不用阻塞主线程等待返回结果
        //中间可以执行别的代码
        Integer result=futureTask.get();//结果已经好了,直接拿出来用
        log.debug("结果是:"+result);
    }

六,多线程调度的先后顺序不由人为控制

多线程调度的先后顺序不由人为控制而是由cpu的任务调度器控制。

    public static void main(String[] args) {
        new Thread(()->{
            while (true){
                log.debug("running");
            }
        },"t1").start();
        new Thread(()->{
            while (true){
                log.debug("running");
            }
        },"t2").start();
    }

我们将上面的代码执行两次得到的结果(取前十个打印):
第一次:
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
14:45:52 [t2] c.Test4 - running
第二次:
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t1] c.Test4 - running
14:52:24 [t2] c.Test4 - running
14:52:24 [t2] c.Test4 - running

七,栈,栈帧

在jvm的内存结构中,栈指的是一个线程运行所需的内存空间,也可以叫栈内存,栈往往与线程挂钩。
每次调用一个方法就和生成一个栈帧。

八,线程常用方法

1.start与run

当创建一个Thread对象,此时这个线程对象并没有纳入任务调度器管理,这个对象必须在执行了start方法之后才会纳入任务调度器调度。
run方法就是重写的Runnable接口的run方法,当Thread对象调用run方法时并没有新开一个线程调用,单单只是这个对象本身调用。

2.sleep和yield

sleep是一个静态方法,只能通过Thread.sleep(休眠时间)调用,Thread.sleep(休眠时间)在哪个线程里面调用就让哪个线程休眠,Thread.sleep(休眠时间)的作用是让当前线程进入休眠,并不参与cpu时间片的竞争,但是sleep方法不会释放锁。
yield也是一个静态方法,只能通过Thread.yield()调用,Thread.yield()在哪个线程里面调用就让哪个放弃对时间片的竞争,注意这个方法时没有时间的,执行完这个方法就表示当前线程放弃对时间片的竞争,但是任务调度器还是可以吧cpu时间片给当前线程。这和setPriority(Thread.MIN_PRIORITY)给线程设置优先级的方法是一样的,yield和setPriority并不能决定任务调度器最后将cpu时间片分给哪个线程。

2.1应用

3.join

当某个线程调用了join方法,作用就是哪个线程调用了join方法,比如t1.join(),作用就是等待t1线程执行完t1.join()才结束,当在主线程调用了t1.join()时,主线程就会阻塞,等待t1.join()结束。

3.1应用

4.interrupt

4.1应用

九,加强线程安全意识(待续)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值