java----线程

《基础概念》

 

 

 

 

 并发:正如我们一边打电话一边开车,大脑的注意力是不断切换的,只是大脑切换的速度很快,所以看起来我们是同时打电话+开车

《线程基本使用》

 

 

 

《继承Thread类,重写run方法》

 

 

《为什么不直接调用run方法而是调用start方法?》

调用start方法后底层会调用start0方法

 

 

 

 《实现Runnable接口,重写run方法》

注意为什么要通过实现Runnable接口,重写run方法来实现创建线程的原因

 

 

 

 《线程不安全》

《问题引出》

模拟售票系统:

 

 但是最后却有这样一种现象,明显是不合理的

 这是因为可能多个线程同时绕过if 判断导致;

《解决----线程同步》

 

 

 

 

 

 这样就解决了上面的问题

 

 多个线程是抢夺同一个锁(同一个对象)才能达到效果

如果上面写成:

 

 

 就会造成如下等不好的影响:

 

《线程退出》

 

 

 

 上面的操作是在main线程中发通知给thread00线程让其终止

《线程常用方法》

 

 

 《守护线程》

 

 在一般情况下,比如我在主线程中开启了一个子线程(t),如果主线程结束,子线程还未结束,那么子线程是不会结束的

为了让子线程跟随主线程共同结束,可以将子线程设置为守卫线程:  t.setDaemon(true);

《线程的生命周期》

Thread.State是枚举类说明可以直接:Thread.State.NEW来表示其生命周期

通过 t.getState() 可以得到现在线程的状态(t是线程)

 

 

 

 

 《线程死锁》

 

 像这样写会造成经典的死锁

因为o1与o2是静态的,则即使在外面创建了两个对象也都是同一个o1,o2;

两个线程,一个线程flag=true,一个线程flag=fasle;

一个线程得到了o1的互斥锁,一个线程得到了o2的互斥锁

再深入后,得到了o1的互斥锁的线程要o2的互斥锁才能进行,另一个同理

这样两个就卡住了,造成死锁

 1 public class Test06 {
 2     public static void main(String[] args) {
 3         new Thread(new Tthread(true)).start();
 4         new Thread(new Tthread(false)).start();
 5     }
 6 }
 7 
 8 class Tthread implements Runnable {
 9     private static Object o1 = new Object();
10     private static Object o2 = new Object();
11     private boolean flag;
12 
13     public Tthread(boolean flag) {
14         this.flag = flag;
15     }
16 
17     @Override
18     public void run() {
19         block();
20     }
21 
22     private void block() {
23         if (flag) {
24             synchronized (o1) {
25                 System.out.println(Thread.currentThread().getName() + "进入到o1的互斥锁"
26                         + "尝试进入o2的互斥锁");
27                 synchronized (o2) {
28                     System.out.println(Thread.currentThread().getName() + "进入到o2的互斥锁");
29                 }
30             }
31         } else {
32             synchronized (o2) {
33                 System.out.println(Thread.currentThread().getName() + "进入到o2的互斥锁"
34                         + "尝试进入o1的互斥锁");
35                 synchronized (o1) {
36                     System.out.println(Thread.currentThread().getName() + "进入到o1的互斥锁");
37                 }
38             }
39         }
40 
41     }
42 }

结果:

 就这样不动了

 《释放锁》

 

 《日后学习对线程的理解》

《为什么在执行单一的任务的时候(比如都是for循环)多线程会比单线程慢?》

参考博客:https://blog.51cto.com/u_12630471/3698074

 

 

 

 

 比如在一些情况下:

我要运行一个程序,其有我输入数据,cpu处理数据,输出数据的过程,这个时候

多线程程序可能比单线程更快

因为如果在单线程的情况下Cpu在处理完数据后就闲置了,花了大量时间在IO操作(IO操作与CPU无关)上,

但是多线程可以利用处理IO操作的时间处理更多数据

如果是像下面单一的for循环任务,cpu无闲置时间,那么单线程速度更快

 《对于多线程上一些奇特的现象的理解》

 《一些语法上的问题》

synchronized(D){S};中的D是我们要上锁的资源,即大家都要抢的资源,其可以是

任何对象,但不能使基本数据类型

《对于临界资源的讲解》

synchronized(D){S;}中的D是临界资源,其实还可以写成synchronized xxx f(){};这种方法的形式

不过这个方法要写在临界资源类中,没错,如果写成方法那么临界资源要专门写成一个类

其中执行的语句是原子级的,所谓原子级是指相关操作是连在一起的,不可分割的,只要少的其中一个操作,那么就执行有缺陷

《线程的同步机制》

同步:线程间执行需要遵守某种约定,java实现同步的方法是:互斥+通信

所谓通信是告诉其他线程自己好了(notify()),然后自己等待(wait())...............这样直到任务结束

像notify(),wait()必须直接或间接的作用域于临界区中,否则会异常

wait()会自己主动释放锁,notify()会激活在临界资源等待队列中的线程;

wait()和notify()都是由临界资源发出

《注意点》

wait(),notify(),     notifyAll()都是Object中的方法,而且都会抛出异常

我想说的一点事在用到wait(),notify()..........的地方不一定要用到synchronized之类的

 

 

posted @ 2022-07-29 11:53  次林梦叶  阅读(19)  评论(0编辑  收藏  举报