java_05线程和多线程

线程和多线程

  • 进程:正在运行的程序
  • 线程: 进程中的一个小任务,线程是进程的一个执行单元,来完成进程中的某一个功能
  • 一个程序运行后至少有一个进程,一个进程可以包含多个线程
  • 单线程程序:若有多个任务只能依次执行,当上一个任务执行结束后,下一个任务开始执行
  • 多线程程序:多个任务可以同时执行
  • 分时调度:所有线程轮流使用cpu使用权,平均分配每个线程占用cpu空间
  • 抢占式调度:优先让优先级高的线程使用cpu,如果线程优先级相同,则会随机选择一个
  • 多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让cpu的使用率更高
  • main方法所在线程称为主线程
  • 同一个主线程中的代码指令按顺序执行,一般不能跳过,原因是:jvm启动后,必然有一个执行路径从main方法开始的,一直执行到main方法结束。当程序的主线程执行时,如果遇到了循环而导致程序在指定的位置停留时间过长,则无法马上执行下面程序,需要等待循环结束后能够执行

Thread类

  • 构造:public Thread()//创建一个默认名字的线程 public Thread(String name)创建一个指定名字的线程

  • 开启线程的第二种方法:声明实现Runnable接口的类,该类然后实现run方法,然后可以分配该类的实例,在创建Thread时候作为一个参数来传递并启动

在这里插入图片描述

  • 创建线程方式一:继承方式

    1. class 子线程类 extends Thread{

      ​ run(){

      ​ 任务代码

      }

      }

  1. 子线程类 t = new 子线程类();
  2. t.start();
  • 创建线程方式二:实现方式
  1. class 实现类 implements Runnable{

    run(){

    }

    }

  2. Thread t = new Thread(new 实现类());

  3. t.start();

  • 从耦合性分析:

    1. 第一种方式:线程和任务紧密结合,耦合性高
    2. 第二中方式:线程和任务之间没有必然联系
  • 从代码扩展性分析:

    1. 第一种方式,由于是继承Thread,那么子线程类就不能继承别的类
    2. 第二种方式,由于是实现了接口,同时可以继承别的类
  • 匿名内部类:快速创建一个类的子类对象,或者一个接口的实现类对象

    1. new 父类(){

      重写方法

      }

    2. new 接口(){

      实现方法

      }

    3. 使用匿名内部类创建线程对象

       new Thread(){
                  @Override
                  public void run() {
                      for (int i = 0; i < 10; i++) {
                          System.out.println("匿名内部类线程"+ i);
                      }
                  }
              }.start();
      
    4. 实现方式

        //实现方式
              Runnable run = new Runnable() {
                  @Override
                  public void run() {
                      for (int i = 0; i < 1000; i++) {
                          System.out.println("第二种线程"+i);
                      }
                  }
              };
              new Thread(run).start();
      
  • 线程安全:当有多个线程同时运行,这些线程必须执行同一个代码,操作同一个共享数据时,可能出现线程的安全问题

  • 实战:买票的问题

    public class TicketsRunnable implements Runnable {
        private  int count = 1000;
        @Override
        public void run() {
            //the task is to 100 tickets
            while (true){
            if(count > 0){
                try{Thread.sleep(50);}catch (Exception e){}
                System.out.println("卖出第"+ count+ "票");
                count--;
            }
            }
        }
    }
    package java学习.Threadings;
    
    public class SaleTicketsDemo {
        public static void main(String[] args) {
            //create a buy tickets task object
            TicketsRunnable tr  = new TicketsRunnable();
            //create three thread object to perform task
            Thread t1 = new Thread(tr);
            t1.start();
            Thread t2 = new Thread(tr);
            t2.start();
            Thread t3 = new Thread(tr);
            t3.start();
        }
    }
    运行会出现问题,出现问题的原因是多个线程相互切换的时间互不相同,同时count的值也存在很大不确定性
    
  • 解决线程安全问题方式一:

    1. 给代码加上锁

      synchronized(对象){

      代码

      }锁对象可以是任何对象

       synchronized (obj){
              while (true){
              if(count > 0){
                  try{Thread.sleep(50);}catch (Exception e){}
                  System.out.println("卖出第"+ count+ "票");
                  count--;
              }
              }
      
    2. 同步方法

      public synchronized void 方法名(){

      }

      同步方法的使用原理和1方法一样,只不过它的对象是this;如果同步方法是静态方法,那么他的对象是类

    3. lock接口实现类:Reentrantlock实现类

      在lock接口中有两个方法:lock() unlock()

线程状态码:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42479155/article/details/88918062
今日推荐