java设计模式和多线程高并发小结后续继续更新

一、设计模式:
java一共有23中设计模式

二、多线程高并发
熟练掌握api,能够完成并发编程
熟读api源码,掌握其原理
理解java虚拟机内存模型
操作系统对并发的支持  


为什么要学习并发编程:

几乎任何一个应用都是并发的多线程的

并发的优点

发挥多核处理器的强大的能力
建模的简单性
异步事件的简化处理
响应更加灵敏的用户界面


1.找工作

2.了解了并发编程,提高代码的编写能力

3.解决工作中遇到的高并发问题

并发的缺点

安全性问题
活越性问题(多个线程是在抢占cpu,秩序混乱,(饥恶状态)(死锁))
性能问题(多线程并不一定快)
线程安全性问题

创建线程的 多种方式
多线程运行 卖票
线程安全性问题
提出解决方案 synchronized
解决线程安全性问题
synchronized原理
。。。


什么是并发?

java代码最终被翻译成字节码,java虚拟机执行的是字节码指令,最终运行在cpu上

并发是多个线程在一块执行

什么是多线程?

每一个线程就是一个顺序执行流

多线程并不一定是并发

​
1
int a=10;
2
int b=20;
3
int c=a+b;
4
System.out.println()
5
    Java虚拟机从上往下顺序执行(java虚拟机中的寄存器)
6
    垃圾收集器(gc),在后台工作(令一个线程在执行)
7
    java虚拟机内存有两个区域
8
        一个是被线程所供享的(堆和方法区)
9
        一个是被线程所独占的(私有线程存储区)
10
    
​
什么是进程?

一个运行中的程序

进程是资源分配的基本的单位

进程中包含着多个线程,线程共享进程的资源

线程是处理器电镀的基本单位。(线程是轻量级的线程,进程在进行切换的时候会浪费更多的资源)

线程一定会快吗?

迅雷多线程下载为什么快

并不是多线程性能提高了

而是由于下载接口多了,最后进行了合并

使得整体的完成时间减少了。

垃圾收集:!!!有空看看。



线程的状态

初始化(start())=》就绪态=》运行态=》终止态(Dead())  



​image.png​



​
1
//先演示下线程之间的状态。
2
public class NewThread implements  Runnable{
3
    @Override
4
    public synchronized void  run() {
5
        while (true){
6
//            System.out.println("自定义的线程运行了");
7
            try {
8
                wait();//等待
9
//                Thread.sleep(100);
10
            } catch (InterruptedException e) {
11
                e.printStackTrace();
12
            }
13
            System.out.println("自定义的线程运行了");
14
        }
15
​
16
​
17
    }
18
​
19
    public static void main(String[] args) {
20
​
21
       NewThread n = new NewThread();
22
        //初始化状态
23
        Thread thread=new Thread(n);//创建了线程,并指定了线程方法
24
​
25
        thread.start();//启动线程
26
        while(true){
27
            synchronized (n){
28
                System.out.println("主线程执行了");
29
                try {
30
                    Thread.sleep(100);
31
                } catch (InterruptedException e) {
32
                    e.printStackTrace();
33
                }
34
                n.notifyAll();//唤醒
35
            }
36
​
37
        }
38
    }
39
​
40
​
41
}
42
​
​
创建线程的多种方式:

继承thread


ThreadGroup  线程组(对线程进行分组)

stackSzie 栈大小(虚拟机课用的)

interrupted() 中断线程

isinterrupted ()判断是否中断

​
1
​
2
//继承Thread创建线程实现多线程
3
public class Demo1 extends Thread {
4
​
5
    public Demo1(String name) {
6
        super(name);
7
    }
8
​
9
​
10
​
11
    public void run() {
12
        while (!interrupted()){//不可以true
13
            System.out.println(getName() + "线程执行了");
14
        try {
15
            Thread.sleep(200);
16
        } catch (InterruptedException e) {
17
            e.printStackTrace();
18
        }
19
    }
20
​
21
}
22
​
23
​
24
    public static void main(String[] args) {
25
        Demo1 d1=new Demo1("线程1");
26
        Demo1 d2 =new Demo1("线程2");
27
​
28
//        d1.setDaemon(true);//守护线程,支持性线程
29
//        d2.setDaemon(true);//守护线程,支持性线程
30
​
31
        d1.start();
32
        d2.start();
33
​
34
        d1.interrupt();//中断
35
//        try {
36
//            Thread.sleep(2000);//休息两秒钟
37
//        } catch (InterruptedException e) {
38
//            e.printStackTrace();
39
//        }
40
    }
41
}
42
​
​


实现Runnable接口


​
1
//实现Runnable接口实现线程的创建
2
public class Demo2 implements  Runnable{
3
    @Override
4
    public void run() {
5
        while (true){
6
            System.out.println("thread running...");
7
        }
8
    }
9
​
10
    public static void main(String[] args) {
11
​
12
        Thread thread=new Thread(new Demo2());
13
        thread.start();
14
    }
15
​
16
}
​


匿名内部类的方式


​
1
//匿名内部类两种方式
2
public class Demo3 {
3
    public static void main(String[] args) {
4
        //继承thread子类实现
5
//        new Thread(){
6
//            public  void run(){
7
//                System.out.println("thread start..");
8
//            }
9
//        }.start();
10
​
11
            //将线程任务作为参数传进去
12
//        new Thread(new Runnable() {
13
//            @Override
14
//            public void run() {
15
//                System.out.println("thread start..");
16
//            }
17
//        }).start();
18
​
19
​
20
​
21
​
22
    new Thread(new Runnable() {
23
        @Override
24
        public void run() {
25
            System.out.println("runnable");
26
        }
27
    }){
28
        public void run(){
29
            System.out.println("sub");
30
        };
31
    }.start();
32
    }
33
}
34
​
​


带返回值的线程


​
1
import java.util.concurrent.Callable;
2
​
3
import java.util.concurrent.FutureTask;
4
//带返回值的线程
5
public class Demo4 implements Callable {
6
​
7
​
8
    public static void main(String[] args) throws Exception{
9
        Demo4 d4=new Demo4();
10
        FutureTask taks =new FutureTask<>(d4);
11
        Thread t=new Thread(taks);
12
        t.start();
13
​
14
        System.out.println("我先干点别的。。");
15
​
16
        Integer result=taks.get();
17
​
18
        System.out.println("线程执行的结果为:"+result);
19
    }
20
​
21
    @Override
22
    public Object call() throws Exception {
23
        System.out.println("正在进行紧张的计算。。。");
24
        Thread.sleep(3000);
25
        return 1;
26
    }
27
}
​


定时器(quartz)


​
1
​
2
import java.util.Timer;
3
import java.util.TimerTask;
4
//定时器
5
public class Demo5 {
6
    public  static  void main(String[] args){
7
        Timer timer=new Timer();
8
        //设置每隔多长时间执行,这个里面有很多方法。
9
        timer.schedule(new TimerTask() {
10
            @Override
11
            public void run() {
12
                System.out.println("timer task is run");
13
            }
14
        },0,1000);
15
    }
16
}
​


应用场景

线程池的实现


​
1
​
2
import java.util.concurrent.Executor;
3
import java.util.concurrent.ExecutorService;
4
import java.util.concurrent.Executors;
5
​
6
//创建了一个池子,里面放的都是线程,用到了线程就从这个里面拿,用完进行回收,有空间换时间。
7
public class Demo6 {
8
    public static void main(String[] args) {
9
//        ExecutorService threadPool = Executors.newFixedThreadPool(10);
10
        ExecutorService threadPool = Executors.newCachedThreadPool();
11
        for (int i = 0; i < 1000; i++) {
12
​
13
​
14
            threadPool.execute(new Runnable() {
15
                @Override
16
                public void run() {
17
                    System.out.println(Thread.currentThread().getName());
18
                }
19
            });
20
        }
21
        threadPool.shutdown();
22
    }
23
​
​


Lambda表达式
函数式开发

更简洁

实现起来更方便

写出的代码性能更高

更支持高并发

​
1
​
2
import java.lang.reflect.Array;
3
import java.util.Arrays;
4
import java.util.List;
5
//lambda表达式并行处理集合
6
public class Demo7 {
7
    public static void main(String[] args) {
8
        List values= Arrays.asList(10,20,30,40);
9
        int res=new Demo7().add(values);
10
        System.out.println("计算结果为:"+res);
11
    }
12
​
13
    public int add(List values){
14
//        values.parallelStream().forEachOrdered(System.out::println);
15
//        return 0;
16
            //jdk可以弱化类型
17
            //paralleStream  //mapToInt
18
      return values.parallelStream().mapToInt(a->a).sum();
19
    }
20
}
21
​
​


spring实现多线程


Config.java

​
1
import org.springframework.context.annotation.ComponentScan;
2
import org.springframework.context.annotation.Configuration;
3
import org.springframework.scheduling.annotation.EnableAsync;
4
​
5
@Configuration
6
@ComponentScan("com.thread.demo1")//配置包扫描
7
@EnableAsync //配置异步
8
public class Config {
9
​
10
}
11
​
​


DemoService.java

​
1
import org.springframework.scheduling.annotation.Async;
2
import org.springframework.stereotype.Service;
3
​
4
@Service
5
public class DemoService {
6
    @Async
7
    public  void a(){
8
        while (true){
9
            System.out.println("a");
10
            try {
11
                Thread.sleep(1000);
12
            } catch (InterruptedException e) {
13
                e.printStackTrace();
14
            }
15
        }
16
​
17
    }
18
    @Async
19
    public void b(){
20
​
21
        while (true){
22
            System.out.println("b");
23
            try {
24
                Thread.sleep(1000);
25
            } catch (InterruptedException e) {
26
                e.printStackTrace();
27
            }
28
        }
29
​
30
    }
31
}
32
​
​


Main.java

​
1
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2
​
3
public class Main {
4
    public static void main(String[] args) {
5
        //加载配置文件
6
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class);
7
       //加载service类
8
        DemoService ds=ac.getBean(DemoService.class);
9
        //执行类中的方法
10
        ds.a();
11
        ds.b();
12
    }
13
}
​


活跃性问题:

死锁
a拥有b需要资源,b也有a需要的资源,哥俩都不释放资源。

饥饿
一块挤着抢吃饭,一直抢不到饭,就被饿死了(线程一直得不到资源)。

饥饿相对应的是公平

饥饿与公平(情景)

高优先级吞噬所有低优先级的cpu时间片
线程永久被阻塞在一个等待进入同步快饿状态
等待线程永远不会被唤醒
如何尽量避饥饿问题:

设置合理的优先级
使用锁来代替synchronized


活锁
让路,然后又在另一条路相遇,又让路,又相遇,反反复复。

性能问题:

多线程执行并不一定快,多线程并一定运行在多核处理器或多个处理器,单个处理器也可以运行多个线程。

时间片:cpu会给每个线程分配一个非常短的时间片,执行完后切换到下一个任务,叫做上下文切换,cpu通过一定算法轮流的切换任务,切换的时候要保存执行状态(因为线程并不一定会在时间片里被执行完),在这个过程中要消耗资源。

线程安全问题:

一个线程在执行的过程中,cpu时间片切换,未执行完的线程被另一条线程所写入的数据所覆盖,形成线程不安全。

多线程环境下
多个线程共享一个资源
对资源进行非原子性操作。
struts2的antion不是线程安全的,要把他设置成为多例。

线程的主题往往都是解决线程安全的问题。

解决线程安全问题

Synchronized原理与使用
内置锁:每一个java类都可以做一个内置锁。

互斥锁:一个线程进来,另一个线程不能进来

原子性:

Synchronized修饰普通方法,内置锁就是当前类的实例。

Synchronized修饰静态方法,

Synchronized修饰代码块。

(锁的概念)任何对象都可以作为锁,那么锁信息又存在对象的什么地方呢?

存在对象头中。

对象头中的信息

Mark Word
线程id
Epoch
对象的分代年龄信息
是否是偏向锁
锁标志位
Class Metada Address
Array Lenth(数组有)
各种锁

偏向锁
每次获取锁和释放锁,会浪费资源
很多情况下,竞争锁不是由多个线程,而是由一个线程在使用。
当多个线程竞争偏向锁的时候他才会释放锁,否者会一直持有锁。
只有一个线程在访问同步代码块的场景。
轻量级锁
多个线程可以同时进入代码块,但不能执行下面的代码,只是在不断自旋。
自旋:自旋就是不断的进行请求,浪费资源。
重量级锁
一个线程拥有则另一个线程必须等待。
单利模式与线程安全问题

懒汉式
进行多线程的时候有非原子性操作。
​
1
//双重判断加锁
2
if(instance==null){
3
    synchronized(Singleton.class){
4
        if(instance==null){
5
            insatnce =new Singleton();
​
指令重排序。

饿汉式
没有线程安全问题
详细解释锁的概念:

锁重入
      a方法被加入入了synchronized锁,在这个方法中调用另一个被加入了synchronized锁的方法b,就会进行锁的重入。

同一个对像的锁只能锁住这个对象的线程,不能锁住其他对象的线程。

​
1
​
2
public class Demo {
3
    public  synchronized void a(){
4
        System.out.println("a");
5
        try {
6
            Thread.sleep(1000);
7
        } catch (InterruptedException e) {
8
            e.printStackTrace();
9
        }
10
//        b();
11
    }
12
    public  synchronized void b(){
13
        System.out.println("b");
14
        try {
15
            Thread.sleep(1000);
16
        } catch (InterruptedException e) {
17
            e.printStackTrace();
18
        }
19
    }
20
​
21
    public static void main(String[] args) {
22
​
23
        Demo d=new Demo();
24
        Demo d2=new Demo();
25
        new Thread(new Runnable() {
26
            @Override
27
            public void run() {
28
//                Demo d=new Demo();
29
                d.a();
30
            }
31
        }).start();
32
​
33
​
34
        new Thread(new Runnable() {
35
            @Override
36
            public void run() {
37
​
38
                d2.b();
39
            }
40
        }).start();
41
    }
42
​
43
}
44
​
​
自旋锁
线程自己在不停地旋转,旋的是CPU时间片,空转cpu,当第一个线程没有执行完毕的时候,其他线程在自旋等待。

死锁


​
1
​
2
public class Demo3 {
3
​
4
    private Object object1=new Object();
5
    private Object object2=new Object();
6
​
7
    public  void a(){
8
        synchronized (object1){
9
            try {
10
                Thread.sleep(10);
11
            } catch (InterruptedException e) {
12
                e.printStackTrace();
13
            }
14
            synchronized (object2){
15
                System.out.println("a");
16
            }
17
        }
18
    }
19
​
20
    public  void b(){
21
        synchronized (object2){
22
            try {
23
                Thread.sleep(10);
24
            } catch (InterruptedException e) {
25
                e.printStackTrace();
26
            }
27
            synchronized (object1){
28
                System.out.println("b");
29
            }
30
        }
31
    }
32
​
33
    public static void main(String[] args) {
34
        Demo3 d5=new Demo3();
35
        new Thread(new Runnable() {
36
            @Override
37
            public void run() {
38
                d5.a();
39
            }
40
        }).start();
41
        Demo3 d=new Demo3();
42
        new Thread(new Runnable() {
43
            @Override
44
            public void run() {
45
                d5.b();
46
            }
47
        }).start();
48
    }
49
​
50
}
51
​
​
数据库中如果发生了死锁,会把死锁的资源给释放掉,很强大。

Volatile

Volatile称之为轻量级锁,被vola修饰的变量,在线程之间是可见的。

可见:一个线程修改了这个变量的值,在另一个线程中能够读到这个修改的值。

Synchronized:除了线程之间互斥外,还有一个非常强大的作用,就是保证可见性。



​
1
​
2
public class Demo3 {
3
​
4
    private Object object1=new Object();
5
    private Object object2=new Object();
6
​
7
    public  void a(){
8
        synchronized (object1){
9
            try {
10
                Thread.sleep(10);
11
            } catch (InterruptedException e) {
12
                e.printStackTrace();
13
            }
14
            synchronized (object2){
15
                System.out.println("a");
16
            }
17
        }
18
    }
19
​
20
    public  void b(){
21
        synchronized (object2){
22
            try {
23
                Thread.sleep(10);
24
            } catch (InterruptedException e) {
25
                e.printStackTrace();
26
            }
27
            synchronized (object1){
28
                System.out.println("b");
29
            }
30
        }
31
    }
32
​
33
    public static void main(String[] args) {
34
        Demo3 d5=new Demo3();
35
        new Thread(new Runnable() {
36
            @Override
37
            public void run() {
38
                d5.a();
39
            }
40
        }).start();
41
        Demo3 d=new Demo3();
42
        new Thread(new Runnable() {
43
            @Override
44
            public void run() {
45
                d5.b();
46
            }
47
        }).start();
48
    }
49
​
50
}
51
​
​
Lock

在多处理器上的系统

将当前处理器缓存行(cpu缓存的最小单位)的内容写回到系统内存

这个写回到内存的操作会使其他cpu里缓存了该内存地址的数据失效

硬盘 --内存--cpu的缓存。

valatile修饰的变量是保证了可见性,但保证不了原子性。

synchronized可以保证原子性和可见性,是在某些方面可以完全替代valatile。



jdk5提供的原子类原理和使用

通过get()方法获取当前的值current

对他进行操作后获取下一个值next

cas方法和下一个值进行比较,如果为真就返回current值,就是线程没有被没有被修改

如果为false就表明被修改过,那就再来一遍。

原子更新基本类型


​
1
​
2
import java.util.concurrent.atomic.AtomicInteger;
3
​
4
public class Sequence {
5
    //原子类基本类型
6
    private AtomicInteger value=new AtomicInteger();
7
    
8
    
9
    public  int getNext(){
10
        return  value.getAndAdd(10);
11
​
12
    }
13
​
14
​
15
    public static void main(String[] args) {
16
​
17
        Sequence s=new Sequence();
18
//        while (true){
19
//            System.out.println(s.getNext());
20
//        }
21
        new Thread(new Runnable() {
22
            @Override
23
            public void run() {
24
                while (true){
25
                    System.out.println(Thread.currentThread().getName()+" "+s.getNext());
26
                    try {
27
                        Thread.sleep(100);
28
                    } catch (InterruptedException e) {
29
                        e.printStackTrace();
30
                    }
31
                }
32
            }
33
        }).start();
34
​
35
        new Thread(new Runnable() {
36
            @Override
37
            public void run() {
38
                while (true){
39
                    System.out.println(Thread.currentThread().getName()+" "+s.getNext());
40
                    try {
41
                        Thread.sleep(100);
42
                    } catch (InterruptedException e) {
43
                        e.printStackTrace();
44
                    }
45
                }
46
            }
47
        }).start();
48
​
49
        new Thread(new Runnable() {
50
            @Override
51
            public void run() {
52
                while (true){
53
                    System.out.println(Thread.currentThread().getName()+" "+s.getNext());
54
                    try {
55
                        Thread.sleep(100);
56
                    } catch (InterruptedException e) {
57
                        e.printStackTrace();
58
                    }
59
                }
60
            }
61
        }).start();
62
    }
63
}
64
​
​


原子更新数组
原子更新抽象类型
原子更新字段
​
1
​
2
import java.util.concurrent.atomic.AtomicInteger;
3
import java.util.concurrent.atomic.AtomicIntegerArray;
4
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
5
import java.util.concurrent.atomic.AtomicReference;
6
​
7
public class Sequence {
8
    //原子类基本类型
9
    private AtomicInteger value=new AtomicInteger();
10
    //原子跟新数组
11
    private  int[] s={2,1,3,4};
12
    AtomicIntegerArray a=new AtomicIntegerArray(s);
13
  //原子更新抽象类型
14
    AtomicReference user=new AtomicReference<>();
15
    //原子跟新字段要更新的字段必须要进行valatile修饰
16
    AtomicIntegerFieldUpdater ord =AtomicIntegerFieldUpdater.newUpdater(User.class,"ord");
17
​
18
    public  int getNext(){
19
    User user=new User();
20
  System.out.println(  ord.getAndIncrement(user));
21
        System.out.println(  ord.getAndIncrement(user));
22
        System.out.println(  ord.getAndIncrement(user));
23
​
24
        a.getAndIncrement(2);
25
    a.getAndAdd(2,10);
26
        return  value.getAndAdd(10);
27
​
28
    }
29
​
30
​
31
    public static void main(String[] args) {
32
​
33
        Sequence s=new Sequence();
34
//        while (true){
35
//            System.out.println(s.getNext());
36
//        }
37
        new Thread(new Runnable() {
38
            @Override
39
            public void run() {
40
                while (true){
41
                    System.out.println(Thread.currentThread().getName()+" "+s.getNext());
42
                    try {
43
                        Thread.sleep(100);
44
                    } catch (InterruptedException e) {
45
                        e.printStackTrace();
46
                    }
47
                }
48
            }
49
        }).start();
50
​
51
        new Thread(new Runnable() {
52
            @Override
53
            public void run() {
54
                while (true){
55
                    System.out.println(Thread.currentThread().getName()+" "+s.getNext());
56
                    try {
57
                        Thread.sleep(100);
58
                    } catch (InterruptedException e) {
59
                        e.printStackTrace();
60
                    }
61
                }
62
            }
63
        }).start();
64
​
65
        new Thread(new Runnable() {
66
            @Override
67
            public void run() {
68
                while (true){
69
                    System.out.println(Thread.currentThread().getName()+" "+s.getNext());
70
                    try {
71
                        Thread.sleep(100);
72
                    } catch (InterruptedException e) {
73
                        e.printStackTrace();
74
                    }
75
                }
76
            }
77
        }).start();
78
    }
79
}
80
​
​


Lock接口

 

你可能感兴趣的:(爬坑日记)