多线程

多线程

并发与并行

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

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

进程与线程

进程:指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。进入到内存中的程序。

线程:线程是进程的一个执行的单位,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程 中是可以有多个线程的,这个应用程序也可以称为多线程程序。

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

Thread

  • public class Thread
    extends Object
    implements Runnable

    线程是程序中执行的线程。Java虚拟机允许应用程序同时执行多个执行线程。

    每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守护程序。 当在某个线程中运行的代码创建一个新的Thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护进程时才是守护线程。

    当Java虚拟机启动时,通常有一个非守护进程线程(通常调用某些指定类的名为main的方法)。 Java虚拟机将继续执行线程,直到发生以下任一情况:

    • 已经调用了Runtime类的exit方法,并且安全管理器已经允许进行退出操作。

    • 所有不是守护进程线程的线程都已经死亡,无论是从调用返回到run方法还是抛出超出run方法的run

    创建一个新的执行线程有两种方法。 一个是将一个类声明为Thread的子类。 这个子类应该重写run类的方法Thread 。 然后可以分配并启动子类的实例。 例如,计算大于规定值的素数的线程可以写成如下:


    class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }


    然后,以下代码将创建一个线程并启动它运行:

    PrimeThread p = new PrimeThread(143); p.start();

    另一种方法来创建一个线程是声明实现类Runnable接口。 那个类然后实现了run方法。 然后可以分配类的实例,在创建Thread时作为参数传递,并启动。 这种其他风格的同一个例子如下所示:


    class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }


    然后,以下代码将创建一个线程并启动它运行:

    PrimeRun p = new PrimeRun(143); new Thread(p).start();

    每个线程都有一个用于识别目的的名称。 多个线程可能具有相同的名称。 如果在创建线程时未指定名称,则会为其生成一个新名称。

    除非另有说明,否则将null参数传递给null中的构造函数或方法将导致抛出NullPointerException

多线程

public class Thread01 extends Thread{
   private String name;

   public Thread01(String name) {
       this.name = name;
  }

   public Thread01() {
  }

   @Override
   public void run() {
       for (int i = 0; i < 20; i++) {
           System.out.println("extends Thread"+i);
      }
  }
}
public class Thread02 implements Runnable {
   private Integer age;

   public Thread02() {
  }

   public Thread02(Integer age) {
       this.age = age;
  }

   @Override
   public void run() {
       for (int i = 0; i < 20; i++) {
           System.out.println("implements Runnable"+i);
      }
  }
}
public class ThreadMain {
   public static void main(String[] args) {
       Thread01 haha = new Thread01("haha");
       haha.start();

       Thread02 thread02 = new Thread02(18);
       new Thread(thread02).start();

       for (int i = 0; i < 20; i++) {
           System.out.println("main"+i);
      }
  }
}

多线程

常用方法:

    • getName() 返回此线程的名称。

    • run()如果这个线程使用单独的Runnable运行对象构造,则调用该Runnable对象的run`方法; 否则,此方法不执行任何操作并返回。

    • sleep(long millis)` 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。

    • start()导致此线程开始执行; Java虚拟机调用此线程的run方法。

    • currentThread() 返回对当前正在执行的线程对象的引用。

/**
* @program: intellij idea
* @description:定义一个thread子类
* @author: lixy
* @create: 2020-05-04 21:18
**/
public class MyThread01 extends Thread {
  @Override
  public void run() {//重写run方法
      String name = getName();
      System.out.println("MyThread01线程名称:"+name);
      Thread thread = MyThread01.currentThread();
      System.out.println(thread);
      System.out.println(Thread.currentThread().getName());
  }
}
public class Demo02Sleep {
  public static void main(String[] args) {
      for (int i = 1; i <= 60; i++) {
          System.out.println(i);

          //使用thread类的sleep方法让程序睡眠
          try {
              Thread.sleep(1000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  }
}

实现Runnable接口创建多线程的好处:

1、避免了单继承的局限性

一个类只能继承一个类,类继承了Thread类就不能继承其他的类

实现Runnable接口,还可以继承其他的类,实现其他的接口。

2、增强了程序的扩展性,降低了程序的耦合性(解耦)

实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)

实现类中,重写了run方法,用来设置线程任务

创建Thread类对象,调用start方法,用来开启新线程。

线程同步

方法:

1、同步代码块

2、同步方法

3、锁机制

多线程

/**
* @program: intellij idea
* @description:实现卖票
* @author: lixy
* @create: 2020-05-04 22:02
**/
public class RunnableImpl implements Runnable {
  private static ArrayList<String> tickets = new ArrayList<String>(Arrays.asList("1号","2号","3号","4号","5号","6号","7号","8号"));
  //创建一个锁对象
  private Object obj = new Object();
  //3-1、在成员位置创建一个
  private Lock lock = new ReentrantLock();
  //设置线程任务:卖票
  @Override
  public void run() {
      //1同步代码块
      /*synchronized (obj){
          //先判断票是否存在
          if (tickets.size()>0){
              int i = new Random().nextInt(tickets.size());
              String ticket = tickets.get(i);
              if (tickets.contains(ticket)){
                  tickets.remove(ticket);
                  System.out.println(Thread.currentThread().getName()+"——存在:"+ticket);
              }
          }
      }*/

      //2、同步方法
      /*metho();*/

      //3、锁机制Lock锁
      lock.lock();//3-2枷锁
      try {
          if (tickets.size()>0){
              int i = new Random().nextInt(tickets.size());
              String ticket = tickets.get(i);
              if (tickets.contains(ticket)){
                  tickets.remove(ticket);
                  System.out.println(Thread.currentThread().getName()+"——存在:"+ticket);
              }
          }
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          lock.unlock();//3-3解锁
      }
  }
  public /*static*/ synchronized void metho(){//静态同步方法
      if (tickets.size()>0){
          int i = new Random().nextInt(tickets.size());
          String ticket = tickets.get(i);
          if (tickets.contains(ticket)){
              tickets.remove(ticket);
              System.out.println(Thread.currentThread().getName()+"——存在:"+ticket);
          }
      }
  }
}

多线程

Wait(等待)与Notify(唤醒)

    • void notify() 唤醒正在等待对象监视器的单个线程。
      void notifyAll() 唤醒正在等待对象监视器的所有线程。
      String toString() 返回对象的字符串表示形式。
      void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
      void wait(long timeout) 导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。
      void wait(long timeout, int nanos) 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法,或者某些其他线程中断当前线程,或一定量的实时时间。
public class Demo04WaitAndNotify {
   public static void main(String[] args) {
       //锁对象
       Object o = new Object();
       new Thread(){
           @Override
           public void run() {
               synchronized (o){
                   System.out.println("等待。。。");
                   try {
                       o.wait();//等待
                  } catch (InterruptedException e) {
                       e.printStackTrace();
                  }
                   System.out.println("开吃。。。");
              }
          }
      }.start();
       new Thread(){
           @Override
           public void run() {
               synchronized (o){
                   System.out.println("唤醒。。。");
                   o.notify();//唤醒
              }
          }
      }.start();
  }
}
运行结果:
等待。。。
唤醒。。。
开吃。。。

 

上一篇:Java架构面试必知必会的微服务面试题解析


下一篇:ubuntu 安装精简桌面