java复盘,⑩多线程

2021/5/4 12:27:20

本文主要是介绍java复盘,⑩多线程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

//mian方法是一个主线程,通过主线程,去调用别的线程
//怎么去确实这个程序是否是多线程呢?
//你可以用一条线,如果程序在运行的时候,能通过这条线穿起来的就是单线程

  • 1.程序:程序存储在硬盘里面,包含可以执行的计算机指令(很多的exe文件,运行指令完成某种功能)和数据静态的实体(静态代码)

  • 2.进程:指的是一个在内存中运行的程序,每一个程序都有一个独立的空间,一个应用程序可以同时运行多个

  • 进程,进程也是程序的一次执行过程,是系统运行程序的一个基本单位,系统运行一个程序即是从一个进行的

  • 创建、运行和消亡的过程。

  • 3.线程:线程是进程中的一个执行单元,负责当前进程中的程序执行,一个进程至少包含一个线程,一个

  • 进程中可以包含多个线程,这个应用程序就是多线程应用程序

  • 4.多线程:在单个程序中同时运行多个线程完成不同的功能,叫做多线程

  • (1)用户想服务器发送了一个请求,服务获取请求并且根据请求响应结果,这就是一个线程

  • (2)客户端N个请求同时去请求服务器,这就是多线程

  • (3)线程有两种调度方式:抢占式调度和

  • 分时调度:所有线程轮流使用cpu的使用权,平均分配每个线程占用cpu的时间,打饭排队的过程

  • 抢占式调度:优先让优先级高的线程使用cup,java就是使用的抢占式,挂急诊,伤重的优先,其他的继续排队的过程

  • 5.并发和并行

  • 并发:一个处理器在同一时间内同时执行多个任务(一个人同时吃两个馒头),(//并发:指的是两个或多个事件在同一时间内发生,交替执行,不好掌控没法确定谁先抢占)

  • 一个时间内有多个时间单位组成,所以说并发的多个任务在单位时间内不一定在同时进行

  • 并行:多个处理器同一时刻同时处理多个不同的任务(两个人同时吃两个馒头)(//并行:指的是两个或多个事件在同一时刻发生)

  • 这是真正同时执行的

  • 显然,并行效率比并发效率高

  • 6.为什么使用多线程?

  • 提高CPU的一个计算能力,避免资源浪费

  • 提高系统的一个响应速度

  • 一直让cpu运行着

  • 7.共享资源

  • 允许多个不同的线程访问同一个资源,最好用实现的方式

  • 8线程的分类(了解)

  • 可以分为用户线程和守护线程

  • (1)用户线程:java创建的线程默认都是用户线程

  • (2)守护线程:后台运行的线程,用于提供后台的服务(gc)

  • 区分:

  • 如果进程中还有用户线程,进程是不会终止的

  • 如果进程中只有守护线程,进程会终止

  • 9.线程的生命周期,分为5个阶段

  • 新建: 当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
    就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件
    运行:当就绪的线程被调度并获得处理器资源时,便进入运行状态, run()方法定义了线程的操作和功能
    阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出 CPU 并临时中止自己的执行,
    进入阻塞状态,堵塞是相当于挂起,临时中止不再去抢了
    注意:yield不是堵塞,他是是放再去抢
    死亡:线程完成了它的全部工作或线程被提前强制性地中止

*/

/**

  • 创建一个子线程,完成1-100之间的自然数的输出,同样主线程执行同样的操作
  • 创建多线程的第一种方式:继承Thread类
  • 1.继承Thread类
    *2.重写run方法 ,线程中实际要执行的业务逻辑
  • 3.创建子类对象
  • 4.调用线程的start()方法

//1.创建一个类继承Thread
class SubThread extends Thread{

//2.重写run方法:线程中实际要执行的业务逻辑
public void run(){
    for(int i=1;i<=100;i++){
        //获取时此线程的名字//Thread.currentThread()
        System.out.println("子线程:"+i);
    }
}

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

    //3.创建一个子类对象
    SubThread sub=new SubThread();
    SubThread sub1=new SubThread();
    //4.调用线程start()方法:启动此线程,调用相应的run方法
    sub.start();

// sub.run();//这就不是一个多线程了,没有启动多线程
//创建一个线程
sub1.start();

    for(int i=1;i<=100;i++){
        System.out.println("主线程:"+i);
    }
}

}

  • Thread类常用的方法
  • 1.void start(): 启动线程,并执行对象的run()方法
    2.run(): 线程在被调度时执行的操作,子线程需要执行的代码放到run方法中
    3.String getName(): 返回线程的名称
    4.void setName(String name):设置该线程名称
    5.static currentThread(): 返回当前线程
    6.yield():调用了此方法的线程立马释放cpu资源执行权
    (当一个线程使用了此方法后,就会把自己cup执行权释放,让给自己或着其他的线程
    ,这个让不是单纯让给别的线程,释放以后自己和别的线程再去抢cpu的执行权)
    7.join():在线程1中调用线程2的join方法,表示执行到此方法后,线程1会进入一个阻塞(停止),
    直到线程2执行完成以后,线程1在接着执行
    8.sleep():让该线程休眠,以毫秒为单位
    令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。
    抛出InterruptedException异常

9:isAlive():判断当前线程是否存活
10。线程通信的方法

11.设置优先级 :默认是5 最小值是1,最大值是10
getPriority():获取线程的优先级值
setPriority():设置线程的优先级
MAX_PRIORITY(10);
MIN _PRIORITY (1);
NORM_PRIORITY (5);

  • 实现线程的第二种方式,
  • 1.创建一个类实现Runnable接口
  • 2.重写Runnable接口的run方法
  • 3.创建一个实现Runnable接口实现类的对象
  • 4.将实现类对象作为形参方式传递给Thread类的构造方法
  • 5.调用start方法,启动线程,并且调用实现类的对象的run方法
  • 继承方式vs实现的方式
  • Thread implements Runnable
  • 那个方式好?实现的方式优先于继承的方式
  • (1)避免了java单继承的问题
  • (2)如果多个线程要操作同一份资源(共享资源),实现的方式更加适合

class PrintNum implements Runnable{

//2.重写run方法
@Override
public void run() {
    for(int i=1;i<=100;i++){
        System.out.println(Thread.currentThread().getName()+":"+i);
    }
}

}

public class TestThread2 {

public static void main(String[] args) {
    //创建一个实现类
    PrintNum p = new PrintNum();

// p.start();会发现没有start方法
// p.run();这样写也不对,没有开启一个线程

    //怎么启动一个线程呢?必须得调用start方法
    Thread t = new Thread(p);/start方法是线程类Thread定义的方法
    t.setName("子线程");
    t.start();//启动一个线程,执行Thread对象生成的构造方法时的形参对象的run方法


    //主线程
    Thread.currentThread().setName("主线程");
    for (int i = 1; i <= 100; i++) {
        System.out.println(Thread.currentThread().getName() + ":" + i);
    }
}
  • 线程通信的三个方法;必须使用在同步代码块或同步方法中

  • wait():等待,一旦一个线程执行wait方法,就相当于释放当前的锁
    *notify()/notifyAll();唤醒wait的一个或者多个线程

  • 死锁
    不同的线程分别占用对方需要的同步资源不放弃,
    都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
    两个人去餐馆吃饭,有一碗饭,只有一双筷子,一只筷子相当于一个锁,一人拿了一支,都不肯放手

  • */
    //在开发中注意代码的抒写,减少死锁

  • 模拟火车站窗口售票,开启三个窗口同时售票,100张票

  • 使用实现的方式实现

  • 1.引起的问题:此线程是存在线程安全问题(错票、重票)

  • 原因:由于一个线程在操作共享数据的过程中,未执行完毕,另外的线程此时也参与

  • 进来了,导致共享数据出现线程安全问题

  • 2.绝对线程安全问题:线程的同步机制

  • 方式1: 同步代码块

  • synchronized (同步监视器){
    // 需要被同步的代码;(为操作共享数据的代码)
    }

1.共享数据:多个线程共同操作同一个数据
2.同步监视器:由一个对象(任何对象)来充当的,哪一个线程获得了此监视器,这个线程就
执行大括号里面的同步代码。可以理解为锁
要求:所有的线程必须共享一把锁
在实现的方式中,一般使用this来充当锁,但是在继承的实现中,不要用this
  • 方式2:同步方法
  • 将操作的共享代码的方法声明为synchronized,该方法就是一个同步方法,
  • 保证其中一个线程执行该方法时,其他线程在外等待直到此线程执行完该方法,
  • 同步方法的锁:谁调用我这个方法谁就是锁,this

static Object obj=new Object();//共享一把锁,锁可以是任何对象



这篇关于java复盘,⑩多线程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程