• 多线程


    一、多线程

          1.并发与并行

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

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

         2.线程和进程

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

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

         3.1.创建线程一

                           1)定义Thread类的子类(继承Thread类),并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行。

                           2)创建Thread子类的实例,即创建了线程对象

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

    例:

    public class MyThread extends Thread {
    
    //定义指定线程名称的构造方法
        public MyThread(String name) {
            //调用父类的String参数的构造方法,指定线程的名称
            super(name);
        }
        /**
         * 重写run方法,完成该线程执行的逻辑
         */
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(getName()+":正在执行!"+i);
            }
        }
        public static void main(String[] args) {
            //创建自定义线程对象
            MyThread mt = new MyThread("新的线程!");
            //开启新线程
            mt.start();
            //在主方法中执行for循环
            for (int i = 0; i < 10; i++) {
                System.out.println("main线程!"+i);
            }
        }
    }

            3.1.1.Thread类的构造方法

               public Thread() :分配一个新的线程对象。

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

               public Thread(Runnable target) :分配一个带有指定目标新的线程对象。

              public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字

           3.1.2.常用方法

           public String getName() :获取当前线程名称。

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

      public void run() :此线程要执行的任务在此处定义代码。

      public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。

      public static Thread currentThread() :返回对当前正在执行的线程对象的引用。 

          3.2.创建线程二

              1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

       2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正 的线程对象。

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

    例:

                 

              3.3.Thread和Runnable的区别 

            如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享;

      实现Runnable接口比继承Thread类所具有的优势:

        1. 适合多个相同的程序代码的线程去共享同一个资源。

        2. 可以避免java中的单继承的局限性。

        3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。

        4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。

         4.线程的同步

           4.1.同步代码块: synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

              

    例:

            同步锁:

                 1. 锁对象 可以是任意类型。

                 2. 多个线程对象 要使用同一把锁。
               注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着

            4.2.同步方法

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

    格式:

             同步锁:

                       对于非static方法,同步锁就是this。
                       对于static方法,我们使用当前方法所在类的字节码对象(类名.class)

              4.3.Lock锁

    • Lock比synchronized代码块和synchronized方法更广泛的锁定操作, 同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。 

                1) public void lock() :加同步锁。

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

                3)Lock接口的实现类ReentrantLock

    例:

             

           5.线程状态

                  

     二、线程池

           1.等待唤醒机制

    • 等待唤醒机制就是用于解决线程间通信的问题的,使用到的3个方法的含义如下:
    1. wait:线程不再活动,不再参与调度,进入 wait set 中,因此不会浪费 CPU 资源,也不会去竞争锁了,这时的线程状态即是 WAITING。它还要等着别的线程执行一个特别的动作,也即是“通知(notify)”在这个对象上等待的线程从wait set 中释放出来,重新进入到调度队列(ready queue)中

    2. notify:则选取所通知对象的 wait set 中的一个线程释放;例如,餐馆有空位置后,等候就餐最久的顾客最先入座。

    3. notifyAll:则释放所通知对象的 wait set 上的全部线程。

    •  调用wait和notify方法需要注意的细节
    1. wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法后的线程。

    2. wait方法与notify方法是属于Object类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Object类的。

    3. wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方法。

        2.线程池

     线程池优点:   

    1. 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

    2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。

    3. 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

    三、Lambda表达式

              借助Java 8的全新语法,上述Runnable接口的匿名内部类写法可以通过更简单的Lambda表达式达到等效:

    public class Demo02LambdaRunnable {
        public static void main(String[] args) {
            new Thread(() -> System.out.println("多线程任务执行!")).start(); // 启动线程
        }
    }
  • 相关阅读:
    利用arcserver 自带tomcat实现上传shapefile、cad等文件,然后用soe解析。
    Linux下ls命令显示符号链接权限为777的探索
    HTTP严格安全传输(HTTP Strict Transport Security, HSTS)chromuim实现源码分析(一)
    利用Python sklearn的SVM对AT&T人脸数据进行人脸识别
    使用sklearn构建含有标量属性的决策树
    SEED缓冲区溢出实验笔记——Return_to_libc
    Python写的嗅探器——Pyside,Scapy
    PySide——Python图形化界面入门教程(六)
    PySide——Python图形化界面入门教程(五)
    PySide——Python图形化界面入门教程(四)
  • 原文地址:https://www.cnblogs.com/cqyp/p/12420568.html
Copyright © 2020-2023  润新知