多线程

day 08

多线程

并发与并行

  1. 并发:指两个或多个事件在同一个时间段内发生。

  2. 并行:指两个或多个事件在同一时刻发生(同时发生)。

  3. 当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为 线程调度。

线程与进程

  1. 进程:

    1. 是指一个内存中运行的应用程序;

    2. 每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;

    3. 进程也是程序的一次执行过程,是系统运行程序的基本单位;

    4. 系统运行一个程序即是一个进程从创建、运行到消亡的过程。

  2. 线程:

    1. 线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。

    2. 一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

  3. 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。

线程

  1. java.lang.Thread 类代表线程

  2. 自定义创建线程

    1. 方式一:继承Thread类

      1. 定义Thread类的子类,并重写该类的run()方法。

      2. run()方法的方法体就是线程需要完成的任务。

      3. 创建Thread子类的实例,即创建了线程对象。

      4. 调用线程对象的start()方法来启动该线程。

    2. 方式二:实现Runnable接口

      1. 创建一个类实现Runnable接口,并重写该类的run()方法。

      2. 创建Runnable实现类的实例,调用public Thread(Runnable target)方法,将实例作为参数target来创建Thread对象。

      3. 调用线程对象的start()方法来启动该线程。

    3. 方式三:匿名内部类

      Runnable r =new Runnable() {
              @Override
              public void run() {
                  
              }
          }
  3. 自定义线程名称

    public Thread(String name) :分配一个指定名字的新的线程对象。
  4. 获取线程名称

    public String getName() :获取当前线程名称。//方式一的获取方式
    public static Thread currentThread() :返回对当前正在执行的线程对象的引用。//方式二的获取方式

线程安全

线程安全

线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

线程同步

同步代码块

  • synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

    synchronized(lock){
        需要同步操作的代码
    }

同步方法

  • 使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。

    public synchronized void method(){
        可能会产生线程安全问题的代码
    }

锁机制

  • java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作。

  • Lock锁也称同步锁,加锁与释放锁方法化了,如下:

    public void lock() :加同步锁。

    public void unlock() :释放同步锁。

  • 创建Lock锁对象:Lock lock = new ReentrantLock();

  • 在需要同步的代码语句前加上同步锁方法,在结束的地方释放同步锁。

线程状态

NEW(新建)、Runnable(可运行)、Blocked(锁阻塞)、Waiting(无限等待)Timed Waiting(计时等待)、Teminated(被终止)

 案例

  • 银行取钱问题
    package ThreadDemo;
    //2.银行取钱模式
    //
    //        两个人AB通过一个账户去银行取钱,A在柜台取钱,B在ATM机取钱。
    //        假设账户总共有10000块, A每次从柜台取出100块,休息100毫秒,B每次从ATM机取出200块,休息200毫秒
    //        在每次取出钱之后,都展示一下用户取出了多少钱,银行账户还剩多少钱。
    //        如此循环往复,直到把账户中的钱取出,结束程序。
    
    public class BankTest {
        public static void main(String[] args) {
            Bank bank = new Bank();
            userA aa = new userA(bank);
            userB bb = new userB(bank);
            new Thread(aa, "用户A").start();
            new Thread(bb, "用户B").start();
        }
    }
    
    class Bank {
        private static int Money = 10000;
    
        public synchronized void A() {
            if (Money >= 100) {
                Money -= 100;
                System.out.println(Thread.currentThread().getName() + "用户取出了100元,银行账户还剩" + Money + "元");
                notify();
            } else {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
        public synchronized void B() {
            if (Money >= 200) {
                Money -= 200;
                System.out.println(Thread.currentThread().getName() + "用户取出了200元,银行账户还剩" + Money + "元");
                notify();
            } else {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    class userA extends Thread {
        private Bank bank;
    
        public userA(Bank bank) {
            this.bank = bank;
        }
    
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                bank.A();
            }
        }
    }
    
    class userB extends Thread {
        private Bank bank;
    
        public userB(Bank bank) {
            this.bank = bank;
        }
    
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                bank.B();
            }
        }
    }
    

      

posted @ 2020-07-02 17:10  庄嘉豪  阅读(164)  评论(0编辑  收藏  举报