• 线程、进程、多线程


    一个进程可以有多个线程,如一个视频,可以同时听声音、看图像、看弹幕等等。

    • 说起进程,就不得不说下程序。程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
    • 进程则是执行春哥徐的一次执行过程,它是一个动态的概念。是系统资源分配的单位。
    • 通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程是CPU调度和执行的单位。

    注意:很多多线程是模拟出来的,真正的多线程是指有多个CPU,即多核,如服务器。如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,CPU只能执行一个代码,因为切换得很快,所以就有了同时执行的错觉。

    核心概念

    • 线程就是独立的执行路径;
    • 在程序运行时,即时没有自己创建线程,后台也会有多个线程,如主线程,GC线程;
    • main()称之为主线程,为系统的入口,用于执行整个程序;
    • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为干预的;
    • 对同一份资源操作时,会存在资源抢夺的问题,需要假如并发控制;
    • 线程会带来额外的开销,如CPU调度时间,并发控制开销;
    • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致;

    三种创建线程的方式:

    代码实现的话,不建议使用“继承Thread类”,避免OOP单继承局限性,推荐使用“实现Runnable接口”,因为它能避免单继承局限性,灵活方便,方便同一个对象被多个线程使用。如下:

    代码实现 方式一:

     1 package com.huolongluo.coindemo.morethread.sub1;
     2 
     3 /**
     4  * Created by 火龙裸 on 2019/11/9.
     5  * desc   : 创建线程方式一:继承Thread类,重写run方法,调用start开启线程。
     6  *
     7  * 总结:线程开启不一定立即执行,由CPU调度执行
     8  * version: 1.0
     9  */
    10 public class TestThread1 extends Thread {
    11     @Override
    12     public void run() {
    13         //run方法线程体
    14         for (int i = 0; i < 20; i++) {
    15             System.out.println("我在看代码--- " + i);
    16         }
    17     }
    18 
    19     public static void main(String[] args) {
    20         //main线程,主线程
    21 
    22         //创建一个线程对象
    23         TestThread1 testThread1 = new TestThread1();
    24         //调用start()方法开启线程
    25         //注意这个地方,假如调用run方法,虽然会执行run里面的代码,但这是调用,一定会先执行完run里面的代码,最后才打印“今天又是奋斗的一天”,多个线程同时执行,应该使用start方法,这样它们才会交替执行。
    26         testThread1.start();
    27 
    28         for (int i = 0; i < 20; i++) {
    29             System.out.println("今天又是奋斗的一天-- " + i);
    30         }
    31     }
    32 }

    代码实现 方式二:

     1 package com.huolongluo.coindemo.morethread.sub1;
     2 
     3 /**
     4  * Created by 火龙裸 on 2019/11/9.
     5  * desc   : 创建线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口的实现类,调用start方法。
     6  * version: 1.0
     7  */
     8 public class TestThread2 implements Runnable {
     9     @Override
    10     public void run() {
    11         //run方法线程体
    12         for (int i = 0; i < 20; i++) {
    13             System.out.println("我在看代码--- " + i);
    14         }
    15     }
    16 
    17     public static void main(String[] args) {
    18         //创建runnable接口的实现类对象
    19         TestThread2 testThread2 = new TestThread2();
    20         //创建线程对象,通过线程对象来开启我们的线程,代理
    21 //        Thread thread = new Thread(testThread2);
    22 //        thread.start();
    23         new Thread(testThread2).start();
    24         for (int i = 0; i < 20; i++) {
    25             System.out.println("今天又是奋斗的一天-- " + i);
    26         }
    27     }
    28 }

    当需要多个线程操作同一个对象是,那就需要想办法处理“并发问题”,代码示例如下:

     1 package com.huolongluo.coindemo.morethread.sub1;
     2 
     3 /**
     4  * Created by 火龙裸 on 2019/11/9.
     5  * desc   : 多线程同时操作同一个对象
     6  * 买火车票例子
     7  * <p>
     8  * 多个线程操作同一个资源对象的情况下,线程不安全,数据紊乱。
     9  * version: 1.0
    10  */
    11 public class TestThread4 implements Runnable {
    12 
    13     //票数
    14     private int ticketNums = 10;
    15 
    16     @Override
    17     public void run() {
    18         while (true) {
    19             if (ticketNums <= 0) {
    20                 break;
    21             }
    22             //模拟延时
    23             try {
    24                 Thread.sleep(200);
    25             } catch (InterruptedException e) {
    26                 e.printStackTrace();
    27             }
    28             System.out.println(Thread.currentThread().getName() + " 拿到了第:" + ticketNums-- + " 张票");
    29         }
    30     }
    31 
    32     public static void main(String[] args) {
    33 
    34         TestThread4 testThread4 = new TestThread4();
    35 
    36         new Thread(testThread4, "小王").start();
    37         new Thread(testThread4, "老师").start();
    38         new Thread(testThread4, "黄牛党").start();
    39     }
    40 }

    执行结果:

    从执行结果中看到,出票顺序出现异常,第1张票同时被两个人拿到,而且还出现第0张票。这就是需要注意处理的多线程并发问题。

  • 相关阅读:
    Java垃圾收集器概述
    redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
    Serialize a Long as a String
    数据库遇到的问题
    解决Safari页面缓存的问题
    idea -> Error during artifact deployment. See server log for details.
    正则表达式
    commons-lang
    Template和Style
    WPF资源
  • 原文地址:https://www.cnblogs.com/huolongluo/p/11825327.html
Copyright © 2020-2023  润新知