初识多线程

一、线程的基本概念:
1、进程:一个程序运行起来之后,叫一个进程。进程拥有代码和打开的文件资源、数据资源、独立的内存空间。

在这里插入图片描述

2、线程:进程里最小的执行单元就是一个线程,一个进程可以有多个线程。线程具有五种状态:New,Runnable,Running,Blocked,Dead

在这里插入图片描述

3、协程/纤程(quasar):比线程更加轻量级的存在,一个线程可以有多个协程,协程在程序内部是可中断的,然后再执行别的执行程序,在适当的时候再返回来接着执行;

在这里插入图片描述

二、线程的启动方式:

public class HowToCreateThread {
    //1、继承thread
    static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Hello MyThread!");
        }
    }

    //2、实现runnable
    static class MyRun implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello MyRun!");
        }
    }

    public static void main(String[] args) {
        new MyThread().start();
        new Thread(new MyRun()).start();
        //3、线程池中执行
        new Thread(()->{
            System.out.println("Hello Lambda!");
        }).start();
    }
}

三、线程相关关键字
1、sleep:睡眠一定时间,线程自动复活,线程回到就绪状态;

2、yield:执行中线程必须得让出当前线程锁一下,其他线程能抢到锁则抢到,抢不到,当前线程继续持有锁。

3、join:当前线程加入其他线程,等待其他join的线程执行完,再执行自己的线程。

4、线程状态

四、原子性操作
在Java中可以通过锁和循环CAS的方式来实现原子操作。

1、synchronized:保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile,可以确保线程互斥的访问同步代码。

2、CAS:自旋锁,循环操作直到成功为止,保证原子操作

1、AtomicLong:以incrementAndGet()为例,对AtomicLong的原理进行说明

public final long incrementAndGet() {
    for (;;) {
        // 获取AtomicLong当前对应的long值
        long current = get();
        // 将current加1
        long next = current + 1;
        // 通过CAS函数,更新current的值
        if (compareAndSet(current, next))
            return next;
    }
}

2、LongAddr:继JDK1.8之后新增的原子类操作

public void increment() {
        add(1L);
    }

LongAdder类与AtomicLong类的区别在于高并发时前者将对单一变量的CAS操作分散为对数组中多个元素的CAS操作,取值时进行求和;而在并发较低时仅对base变量进行CAS操作,与AtomicLong类原理相同。

3、synchronized、AtomicLong、LongAddr针对100000000数据执行效率对比

public class AtomicVsSyncVsLongAdder {
    static long count2 = 0L;
    static AtomicLong count1 = new AtomicLong(0L);
    static LongAdder count3 = new LongAdder();

    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[1000];

        for(int i=0; i<threads.length; i++) {
            threads[i] =
                    new Thread(()-> {
                        for(int k=0; k<100000; k++) count1.incrementAndGet();
                    });
        }

        long start = System.currentTimeMillis();

        for(Thread t : threads ) t.start();

        for (Thread t : threads) t.join();

        long end = System.currentTimeMillis();

        System.out.println("Atomic: " + count1.get() + " time " + (end-start));
        //-----------------------------------------------------------
        Object lock = new Object();

        for(int i=0; i<threads.length; i++) {
            threads[i] =
                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        for (int k = 0; k < 100000; k++)
                            synchronized (lock) {
                                count2++;
                            }
                    }
                });
        }

        start = System.currentTimeMillis();

        for(Thread t : threads ) t.start();

        for (Thread t : threads) t.join();

        end = System.currentTimeMillis();

        System.out.println("Sync: " + count2 + " time " + (end-start));

        //----------------------------------
        for(int i=0; i<threads.length; i++) {
            threads[i] =
                    new Thread(()-> {
                        for(int k=0; k<100000; k++) count3.increment();
                    });
        }

        start = System.currentTimeMillis();

        for(Thread t : threads ) t.start();

        for (Thread t : threads) t.join();

        end = System.currentTimeMillis();
        System.out.println("LongAdder: " + count1.longValue() + " time " + (end-start));

    }
}

执行结果如下:

五、锁升级的概念
sync(Object)

1、线程的初始状态是无锁

2、markword:如果当前是第一个线程访问的时候。没个这个线程枷锁,记录当前线程的ID(偏向锁),默认将来不会有第二个线程来抢这个锁,单个线程执行的状态。

3、如果有线程争用:升级为自旋锁,默认自旋10次。

4、10次之后,升级为重量级锁,自己去操作系统申请资源。

关于锁的选择:

加锁代码执行时间断,线程数少,使用自旋锁(CAS)。

加锁代码执行时间长,线程数比较多,使用系统锁(synchronized)。

在这里插入图片描述
您的每一份关注,都是我不懈成长的动力

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值