线程

1. 什么是进程?什么是线程?

​ 进程是一个应用程序(一个进程是一个软件),线程是一个进程中的执行场景/执行单元,一个进程可以启动多个线程。

对于Java程序来说,当在DOS命令窗口输入:Java HelloWorld回车换行之后会启动JVM,而JVM就是一个进程。JVM在启动一个主线程调用main方法。同时在启动一个垃圾回收线程负责看护,现在的Java程序中至少有两个线程并发,一个是垃圾回收线程,一个执行main方法的主线程。

2. 进程和线程之间的关系

​ 例:

​ 阿里巴巴:进程

​ 马云:阿里巴巴的一个线程

​ 童文红:阿里巴巴的一个线程
注意:
进程A和进程B的内存独立不共享。(阿里巴巴和京东资源不共享)

​ 线程A和线程B,堆内存和方法区内存共享

​ 但是栈内存独立,一个线程和一个栈。

​ java中之所以有多线程机制,目的是为了提高程序的处理效率

main方法结束只是主线程结束了,主栈空了,其它的栈可能还在压栈弹栈

3. 堆和方法区共享栈独立

在这里插入图片描述

4.多线程并发的理解

分析一个问题:对于单核的CPU来说,真的可以做到真正的多线程并发吗?

 对于多核的CPU电脑来说,真正的多线程并发是没问题的。

 4核cPU表示同一个时间点上,可以真正的有4个进程并发执行。

什么是真正的多线程并发?

 t1线程执行t1的。

 t2线程执行t2的.

t1不会影响t2, t2也不会影响t1.这叫做真正的多线程并发。

单核的CPU表示只有一一个大脑:

不能够做到真正的多线程并发,但是可以做到给人一种多线程并发"的感觉。对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但是由于CPU的处理速度极快,多个线程之间频繁切换执行,跟人来的感觉是:多个事情同时在做!!!

线程A:播放音乐

线程B:运行魔兽游戏

线程A和线程B频繁切换执行,人类会感觉音乐一直在播放,游戏- -直在运行,给我们的感觉是同时并发的。

电影院采用胶卷播放电影,一个胶卷-一个胶卷播放速度达到一-定程度之后,

人类的眼睛产生了错觉,感觉是动画的。这说明人类的反应速度很慢,就像

–根钢针扎到手上,到最终感觉到疼,这个过程是需要很长的"时间的,在

这个期间计算机可以进行亿万次的循环。所以计算机的执行速度很快.

4. 实现线程的第一种方式

在这里插入图片描述
在这里插入图片描述

5.run和start的区别

在这里插入图片描述
在这里插入图片描述

6. 实现线程的第二种方式

在这里插入图片描述
在这里插入图片描述

6.1 采用匿名内部类方式实现

在这里插入图片描述

7. 线程的生命周期

新建状态、就绪状态、运行状态、阻塞状态、死亡状态
在这里插入图片描述

8. 获取线程的名字

在这里插入图片描述

9. 获取当前对象

在这里插入图片描述

10. 线程的sleep方法

在这里插入图片描述
在这里插入图片描述

11. 终止线程的睡眠

在这里插入图片描述
在这里插入图片描述

12. 合理的终止一个线程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

13. 线程调度

13.1 线程调度概述
         关于线程的调度:
            * 常见的线程调度模型有哪些?
                  抢占式调度模型:
                       哪个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些,Java采用的就是抢占式调度模型。
                  均分式调度模型:
                       平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样,有一些编程语言线程调度采用这种方式。
13.2 线程调度方法

Java提供了哪些方法是和线程调度有关系的呢?

 实例方法:
    void setPriority(int newPrority) 设置线程的优先级
    int getPriority() 获取线程优先级
    最低优先级 1
    默认优先级 5
    最高优先级 10
    优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的)
    
 静态方法:
     static void yield() 让位方法
     暂停当前正在执行的线程对象,并执行其他线程
     yield() 方法不是阻塞方法。让当前线程让位,让给其他线程使用。
     yield() 方法的执行就绪之后,有可能会再次抢到
     
  实例方法:
     void join() 
     合并线程
     class MyThread1 extends Thread {
              public void doSome(){
                       MyThread2 t = new MyThread2();
                      t,join();  //当前线程进入阻塞,t线程执行,直到t线程结束。当前线程才可以
         }
     }
      class MyThread2 extends Thread{
      }

14. 线程安全

关于多线程并发环境下,数据的安全问题。

  1.为什么这个是重点?
       以后在开发中,我们的项目都是运行在服务器当中,而服务器已经将线程的定义,线程的对象创建,线程的启动等,都已经实现完了。这些代码我们都不需要编写。
       重要的是:你要知道,你编写的程序需要放到一个多线程的环境下运行,你更需要关注的是这些数据在多线程并发环境下是否是安全的。
   2.什么时候数据在多线程并发的环境下会存在的安全问题?
       三个条件:
            条件一:多线程并发
            条件二:有共享数据
            条件三:共享数据有修改的行为
       满足以上3个条件之后,就会存在线程安全问题    

14.1 举例
在这里插入图片描述

14.2 如何解决线程安全
怎么解决线程安全问题?

	当多线程并发的环境下,有共享数据,并且这个数据还会被修改,此时就存在线程安全问题,如何解决?
	   线程排队执行(不能并发)
	   用排队执行解决线程安全问题
	   这种机制被称为:线程同步机制
	   专业术语叫做:线程同步,实际上就是线程不能并发了。线程必须排队执行

       使用线程同步机制可以解决线程安全问题,线程同步就是线程排队,线程排队会牺牲一部分效率。
14.3 同步和异步的理解

关于线程同步有异步编程模型和同步编程模型:
异步编程模型:
线程t1和线程t2,各自执行各自的,t1不管t2,t2不管t1,谁也不需要等谁,这种编程模型叫做:异步编程模型。也就是多线程并发(效率较高)
异步就是并发
同步编程模型:
线程t1和线程t2,在线程t1执行的时候,必须等待t2线程执行结束,或者说在t2线程执行的时候,必须等待t1线程执行结束,两个线程之间发生了等待关系,这就是同步编程模型。效率较低,线程排队执行。
同步就是排队

15. 同步代码块synchronized

线程同步机制的语法是:

​ synchronized(){

​ 编程同步代码块

​ }

synchronized后面小括号中传的这个“数据“,是多线程共享的数据。才能达到多线程排队
在这里插入图片描述

16. Java中的三大变量

Java中有三大变量?
     实例变量:在堆中
     静态变量:在方法区中
     局部变量:在栈中
以上三大变量中:
     局部变量永远不会存在线程安全问题,因为局部变量不共享(一个线程一个栈),局部变量在栈中。所以局部变量永远都不会共享。
     
     实例变量在堆中,堆只有一个
     静态变量在方法区中,方法区只有一个
     堆和方法都是多线程共享的,可能会存在线程安全问题。

17. synchronized的三种写法

第一种:同步代码块(灵活)
		synchronized(线程共享对象){
		   同步代码块
				}
				
第二种:在实例方法上使用synchronized
        表示共享对象一定是this,并且同步代码块是整个方法体。
        
第三种:在静态方法上使用synchronized
        表示找类锁,类锁永远只有一把,就算创建了100个对象,那类锁也只有一把。

对象锁:1个对象1把锁,100个对象100把锁。
类锁:100个对象,也可能只有1把类锁

18. 死锁概述

public class Test01 {
    public static void main(String[] args) {

        Object o1 = new Object();
        Object o2 = new Object();
        Thread t1 = new Mythread1(o1,o2);
        Thread t2 = new Mythread2(o1,o2);

        t1.start();
        t2.start();
    }
}
class Mythread1 extends Thread{
    Object o1;
    Object o2;
    public Mythread1(Object o1,Object o2){
        this.o1=o1;
        this.o2=o2;
    }
    @Override
    public void run() {
           synchronized (o1){
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               synchronized (o2){

               }
           }
    }
}
class Mythread2 extends Thread{
    Object o1;
    Object o2;
    public Mythread2(Object o1,Object o2){
        this.o1=o1;
        this.o2=o2;
    }
    @Override
    public void run() {
        synchronized (o2){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){

            }
        }
    }
}

19. 开发中如何解决线程安全问题

是不是一上来选择线程同步?
    不是,synchronized会让程序的执行效率降低,用户体验不好。系统的用户吞吐量降低。用户体验差。在不得已的情况下在选择线程同步机制。

第一种方案:尽量使用局部变量代替“实例变量”和“静态变量”

第二种方案:如果必须是实例变量,那么可以考虑创建多个对象,这样实例变量的内存就不共享了。(一个线程对应1个对象,100个线程对应100个对象,对象不共享,就没有数据安全问题)

第三种方案:如果不能使用局部变量,对象也不能创建多个,这个时候就只能选择synchronized了。线程同步机制

20. 守护线程概述

守护线程的特点:
一般守护线程是一个死循环,所有的用户线程只要结束,守护线程自动结束。

注意:主线程main方法是一个用户线程

守护线程用在什么地方?
举例:每天00:00的时候系统数据自动备份。这个时候需要使用到定时器,并且我们可以将定时器设置为守护线程。一直在那里看着,每到00:00的时候就备份一次。所有的用户线程如果结束了,守护线程自动退出,没有必要进行数据备份了。

public class Test06 {
    public static void main(String[] args) {

        Thread t1 = new Mythread6();
        t1.setName("备份数据系统");
        //启动线程之前将线程设置为守护线程
        t1.setDaemon(true);
        t1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"主线程"+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Mythread6 extends Thread{
    @Override
    public void run() {
        int i = 0;
        //即使是死循环,但由于该线程是守护者,当用户线程结束,守护线程自动终止
        while (true){
            System.out.println(Thread.currentThread().getName()+"--->"+(++i));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

21. 实现定时器

在这里插入图片描述

22. 实现线程的第第三种方式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

23. 生产者和消费者模式

关于Object类中的wait方法和notify方法(生产者和消费者模式)

	第一:wait和t.notify方法不是线程对象的方法,是Java中任何一个Java对象都有的方法,因为这两个方法是Object类中自带的。
	  wait方法和notify方法不是通过线程对象调用
	  举例:t.wait()和t.notify()都是错误的
	  
	第二:wait()方法作用?
			Object o = new Object();
			o.wait();
     表示:让正在o对象上活动的线程进入等待状态,无期限等待,直到被唤醒为止。
     		o.wait()  方法的调用,会让“当前线程(正在o对象上活动的线程)”进入等待状态
	
	第三:notify()方法作用?
		Object o = new Object();
		o.notify();
		表示:唤醒正在o对象上等待的线程。
		还有一个notifyAll()方法:唤醒o对象上处于等待的所有进程。

在这里插入图片描述

所有资料均来自网络个人收集整理,仅供所有Java编程爱好者学习参考!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值