• 多线程


    多线程

    并发与并行

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

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

    进程与线程

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

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

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

    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

    image-20200504210103641

    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);
          }
      }
    }

    image-20200504210803684

    常用方法:

      • 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、锁机制

    image-20200504234834103

    /**
    * @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);
              }
          }
      }
    }

    image-20200505000423813

    Wait(等待)与Notify(唤醒)

      • voidnotify() 唤醒正在等待对象监视器的单个线程。
        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();
      }
    }
    运行结果:
    等待。。。
    唤醒。。。
    开吃。。。

     

  • 相关阅读:
    ubuntu安装node.js+express+mongodb
    Linux(Ubuntu)下安装NodeJs
    Nodejs的Express完成安装指导
    【详解】ERP、APS与MES系统是什么?
    linux常用命令
    Linux命令集合
    sql 以逗号分割成多行数据
    【项目管理工具】SVN
    富文本编辑器
    cookie的跨页面传值
  • 原文地址:https://www.cnblogs.com/lxy522/p/12829809.html
Copyright © 2020-2023  润新知