【多线程与高并发】--相关知识梳理---提升自己值得拥有

前言

本篇博客主要总结了,多线程与高并发相关知识,目的是提升自己技术能力同时也能帮助你。


1.线程中的run与start的区别

package com.zcw.demo.demo1;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName : ZCWThread
 * @Description :线程中start 方法与run方法
 * @Author : Zhaocunwei
 * @Date: 2020-06-13 13:39
 */
public class ZCWThread {
    private static class T1 extends  Thread{
        @Override
        public void run(){
            for(int i=0;i<10;i++){
                try {
                    TimeUnit.MICROSECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("T1");
            }
        }
    }

    public static void main(String[] args) {
        new T1().start();
//        new T1().run();
        for(int i=0;i<10;i++){
            try {
                TimeUnit.MICROSECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("main");
        }
    }
}



运行结果:

在这里插入图片描述
在这里插入图片描述
通过上面两个图分析原因,当我们调用start方法时,会在调用start方法那里产生分支,这个分支和我的主程序一起执行,run方法呢,就一个执行路径。

2.创建线程的两种方式-启动线程程序的三种方式

package com.zcw.demo.demo1;

/**
 * @ClassName : HowToCreateThread
 * @Description :创建线程的两种方式
 * @Author : Zhaocunwei
 * @Date: 2020-06-13 14:15
 */
public class HowToCreateThread {
    static class MyThread extends Thread{
        @Override
        public void run (){
            System.out.println("Hello MyThread!");
        }
        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();
                new Thread(() ->{
                    System.out.println("Hello lambda!");
                }).start();
            }
        }
    }
}



启动线程的三种方式:
1.Thread
2.Runnable
3.Executors.newCachedThrad

3.线程中的基本方法

package com.zcw.demo.demo1;

/**
 * @ClassName : Sleep_yield_Join
 * @Description :线程中的基本方法
 * @Author : Zhaocunwei
 * @Date: 2020-06-13 14:24
 */
public class Sleep_yield_Join {
    public static void main(String[] args){
        //testSleep();
        //testYield();
        //testJoin();
    }
    static void testSleep(){
        new Thread(()->{
            for(int i=0;i<100;i++){
                System.out.println("A"+i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
    static void testYield(){
        new Thread(()->{
            for(int i=0;i<100;i++){
                System.out.println("A"+i);
            }
        }).start();
        new Thread(()->{
            for(int i=0;i<100;i++){
                System.out.println("------------------------B"+i);
                if(i%10 == 0){
                    Thread.yield();
                }
            }
        }).start();
    }
    static void testJoin(){
        Thread t1= new Thread(()->{
            for(int i=0;i<100;i++){
                System.out.println("A"+i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(() ->{
            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for(int i=0; i<100; i++){
                System.out.println("A"+i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t2.start();
    }
}



  • 线程状态

package com.zcw.demo.demo1;

/**
 * @ClassName : ThreadState
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-13 14:54
 */
public class ThreadState {
    static class MyThread extends Thread{
        @Override
        public void run(){
            System.out.println(this.getState());
            for (int i=0;i<10;i++){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(i);
            }
        }
    }

    public static void main(String[] args) {
        Thread t = new MyThread();
        System.out.println(t.getState());
        t.start();
         try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t.getState());
    }
}


4.Synchronized关键字对某个对象加锁

package com.zcw.demo.demo1;

/**
 * @ClassName : MySynchronized
 * @Description : Synchronized关键字对某个对象加锁
 * @Author : Zhaocunwei
 * @Date: 2020-06-13 15:20
 */
public class MySynchronized {
    private static int count=10;
    private Object o = new Object();

    public void m(){
        //任何线程要执行下面的代码,必须先拿到0的项
        synchronized (o){
            count --;
            System.out.println(Thread.currentThread().getName()+" count="+count);
        }
    }
    //考虑一下这里? synchronized(this)是否可以?
    public static void  mm(){
        synchronized (MySynchronized.class){
            count --;
        }
    }
}



  • synchronized(Object)不能用String,常量,Integer long
  • 线程同步
    synchronized
    1.锁的是对象不是代码
    2.this xxx.class
    3锁定方法,非锁定方法同时执行。
    4.锁升级: 偏向锁,自旋锁,重量级锁,线程数少,自旋锁多。
    操作消耗时间长,重量级锁

5.Volatile

  • 保证线程可见性
  • 禁止指令重排序
    – DCL单例
    –Double Check Lock
    –Mgr06.java
package com.zcw.demo.demo2;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName : T
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-15 12:22
 */
public class T {
    /**volatile**/ boolean running =true;//对比一下在volatile的情况下,整个程序运行结果的区别
    void m(){
        System.out.println("m start");
        while(running){
            try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println("m end");
    }

    public static void main(String[] args) {
        T t = new T();
        new Thread(t::m,"t1").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.running=false;
    }
}


  • 运行结果:
m start
m end

  • 单例
    饿汉式:
    类加载到内存中后,就实例化一个单例,JVM保证线程安全,简单实用,推荐使用,但是它的缺点是,不管用与否,类装载时就实例化,Class.forName("")
package com.zcw.demo.demo2;

/**
 * @ClassName : Mgro1
 * @Description :饿汉式
 * @Author : Zhaocunwei
 * @Date: 2020-06-15 12:44
 */
public class Mgro1 {
    private static final Mgro1 INSTANCE = new Mgro1();
    private Mgro1(){};
    public static Mgro1 getInstance(){
        return INSTANCE;
    }
    public void m(){
        System.out.println("m");
    }

    public static void main(String[] args) {
        Mgro1 m1 = Mgro1.getInstance();
        Mgro1 m2 =Mgro1.getInstance();
        System.out.println(m1==m2);
    }
}



  • 运行结果:

true

  • 懒汉式
    1.线程不安全的

package com.zcw.demo.demo2;

/**
 * @ClassName : Mgr03
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-15 12:50
 */
public class Mgr03 {
    private static Mgr03 INSTANCE;
    private Mgr03(){

    }
    public static Mgr03 getInstance(){
        if(INSTANCE == null){
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE= new Mgr03();
        }
        return INSTANCE;
    }
    public void m(){
        System.out.println("m");
    }

    public static void main(String[] args) {
        for(int i=0; i<10;i++){
            new Thread(()->
            System.out.println(Mgr03.getInstance().hashCode())
            ).start();
        }
    }
}


  • 运行结果:
1899625310
524631667
860147208
653846628
101695638
315181923
810466593
319155376
1035305589
1035305589


把上面的类创建为线程安全的:

package com.zcw.demo.demo2;

/**
 * @ClassName : Mgr04
 * @Description : lazy loading
 *                 也称为懒汉式
 *                 虽然达到了按需初始化的目的,但是带来了线程不安全的问题,
 *                 可以通过synchronized解决,但也带来效率下降
 * @Author : Zhaocunwei
 * @Date: 2020-06-15 12:55
 */
public class Mgr04 {
    private static Mgr04 INSTANCE;
    private Mgr04(){

    }
    public static synchronized  Mgr04 getInstance(){
        if(INSTANCE == null){
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Mgr04();
        }
        return  INSTANCE;
    }
    public void m(){
        System.out.println("m");
    }

    public static void main(String[] args) {
        for(int i =0;i<10;i++){
            new Thread(()->{
                System.out.println(Mgr04.getInstance().hashCode());
            }).start();
        }
    }
}


  • 运行结果:
554241184
554241184
554241184
554241184
554241184
554241184
554241184
554241184
554241184
554241184

  • 单例模式添加volatile解决指令重排序问题

package com.zcw.demo.demo2;

/**
 * @ClassName : Mgr06
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-15 13:11
 */
public class Mgr06 {
    private static volatile Mgr06 INSTANCE;
    private Mgr06(){

    }
    public static Mgr06 getInstance(){
        if(INSTANCE ==null){
            synchronized (Mgr06.class){
                if(INSTANCE ==null){
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Mgr06();
                }
            }
        }
        return INSTANCE;
    }
    public void m(){
        System.out.println("m");
    }

    public static void main(String[] args) {
        for(int i=0;i<100;i++){
            new Thread(()->{
                System.out.println(Mgr06.getInstance().hashCode());
            }).start();
        }
    }
}


  • 运行结果:
315181923
315181923
315181923
315181923
315181923
315181923
 ... ...

5.CAS(无锁优化 自旋)

  • Compare And Swap
  • 原子性
package com.zcw.demo.demo2;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName : AtomicInteger
 * @Description :
 * @Author : Zhaocunwei
 * @Date: 2020-06-15 13:48
 */
public class MyAtomicInteger {
    AtomicInteger count = new AtomicInteger(0);
    void m(){
        for(int i=0;i<1000;i++){
            count.incrementAndGet();
        }
    }

    public static void main(String[] args) {
        MyAtomicInteger t = new MyAtomicInteger();
        List<Thread> threads = new ArrayList<>();
        for(int i=0;i<10;i++){
            threads.add(new Thread(t::m,"thread-"+i));
        }
        threads.forEach((o)->o.start());
        threads.forEach((o)->{
            try {
                o.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(t.count);
    }

}


  • 运行结果:
10000

出现ABA问题

– 加version,或者添加标签解决问题
weakCompareAndSetObject


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章