Chapter17_多线程
侧边栏壁纸
  • 累计撰写 53 篇文章
  • 累计收到 5 条评论

Chapter17_多线程

bbchen
2023-02-26 / 0 评论 / 44 阅读 / 正在检测是否收录...

多线程初步

image-20221020111758098

概念

程序

是为了完成特定任务,用某种语言编写的一组指令的集合

进程

  1. 进程是运行中的程序,比如我们使用 QQ,就启动了一个进程,操作系统就会为该进程分配内存空间,当我们使用微信,有启动了一个进程,操作系统将为微信分配新的内存空间
  2. 进程是程序的一次执行过程,或是正在运行的一个程序,是动态过程,有它自身的产生、存在和消亡的过程

线程

  1. 线程是由进程创建的,是进程的一个实体
  2. 一个进程可以拥有多个线程

单线程

同一个时刻,只允许执行一个线程

多线程

同一个时刻,可以执行多个线程

并发

同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单来说,单核 CPU 是实现的多任务就是并发

并行

同一个时刻,多个任务同时执行,多核 CPU 可以实现并行

线程基本使用

  1. 继承 Thread 类, 重写 run 方法
  2. 实现 Runnable 接口,重写 run 方法

image-20221026143857143

真正实现多线程效果的,是start0(),而不是 run()

package com.bbedu.threadUse;

public class Thread03 {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new T1());
        Thread thread2 = new Thread(new T2());

        thread1.start();
        thread2.start();
    }
}

class T1 implements Runnable {

    int count = 0;
    @Override
    public void run() {
        while (true) {
            System.out.println("hello~ " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 30) {
                break;
            }
        }
    }
}

class T2 implements Runnable {

    int count = 0;
    @Override
    public void run() {
        while (true) {
            System.out.println("hi~ " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 40) {
                break;
            }
        }
    }
}

Thread 和 Runnable 的区别

image-20221026204135436

线程常用方法

image-20221026211304722

练习

image-20221027100714080

package com.bbedu.method;

public class ThreadMethodExercise {

    public static void main(String[] args) throws InterruptedException {

        T2 t2 = new T2();

        for (int i = 1; i <= 10; i++) {
            System.out.println("hi " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (i == 5) {
                t2.start();
                t2.join();
            }
        }
        System.out.println("主线程结束...");
    }

}

class T2 extends Thread{

    int num = 0;

    @Override
    public void run() {
        while (num < 10) {
            System.out.println("hello " + (++num));

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("子线程结束...");
    }
}

线程七大状态

image-20221027104446798

Synchronized

image-20221027110703785

互斥锁

  1. Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
  2. 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,能有一个线程访问该对象。
  3. 关键字synchronized来与对象的互斥锁联系。当某个对象 synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问
  4. 同步的局限性:导致程序的执行效率要降低
  5. 同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)
  6. 同步方法(静态的)的锁为当前类本身。

细节

  1. 同步方法如果没有使用static修饰:默认锁对象为this
  2. 如果方法使用static修饰,默认锁对象:当前类.class
  3. 实现的落地步骤:
    需要先分析上锁的代码选择同步代码块或同步方法
    要求多个线程的锁对象为同一个即可!

作业

image-20221027130816663

package com.bbedu.homework;

import java.util.Map;
import java.util.Random;
import java.util.Scanner;

public class Homework01 {
    public static void main(String[] args) {
        T01 t01 = new T01();
        T02 t02 = new T02(t01);
        t01.start();
        t02.start();
    }
}

class T01 extends Thread {

    private boolean loop = true;

    @Override
    public void run() {
        while (loop) {
            System.out.println((int)(Math.random() * 100 + 1));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }
}

class T02 extends Thread {

    private T01 t01;
    private Scanner scanner = new Scanner(System.in);

    public T02(T01 t01) {
        this.t01 = t01;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println("输入q结束");
            char c = scanner.next().toUpperCase().charAt(0);
            if (c == 'Q') {
                t01.setLoop(false);
                System.out.println("t01退出");
                break;
            }
        }
    }
}

image-20221027130904156

package com.bbedu.homework;

public class Homework02 {
    public static void main(String[] args) {
        Withdraw withdraw = new Withdraw();

        Thread thread1 = new Thread(withdraw);
        Thread thread2 = new Thread(withdraw);

        thread1.start();
        thread2.start();
    }
}

class Withdraw implements Runnable {

    static final Object obj = new Object();
    private static int total = 10000;
    private boolean loop = true;

    public void withdraw() {
        synchronized (obj) {
            if (total <= 0) {
                loop = false;
                return;
            }

            total -= 1000;
            System.out.println("用户 " + Thread.currentThread().getName() +
                    " 取出1000元" + " 剩余=" + total);

        }
    }


    @Override
    public void run() {
        while (loop) {
            withdraw();
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
0

评论

博主关闭了所有页面的评论