• java多线程


    参考:java多线程与并发(基础篇)

    附:https://www.cnblogs.com/zsql/p/11144688.html

      https://www.cnblogs.com/wxd0108/p/5479442.html

    Java多线程:彻底搞懂线程池:https://blog.csdn.net/u013541140/article/details/95225769

     

      1 package org.java;
      2 
      3 import java.util.Random;
      4 /*
      5  Java多线程:
      6  多线程:指同时存在几个执行体,按几条不同的执行线索共同工作的情况
      7          实际上并不是同时,而是Java快速的控制一个线程切换到另一个线程
      8  单线程:一个程序(一个进程)从头到尾 只有一条执行线索
      9 
     10 
     11 进程与线程
     12 进程:是系统进行资源分配和调度的基本单位。
     13 线程:一个进程中至少有一个线程,进程中的多个线程共享进程的 资源。
     14         系统是把资源分给进程,但是CPU很特殊,是被分配到线程的
     15             所以线程是CPU分配的基本单位。
     16 一个进程中有多个线程,多个线程共享进程的堆和方法区资源
     17     但是每个线程有自己的程序计数器和栈区域。
     18 程序计数器:是一块内存区域,用来记录线程当前要执行的指令地址 。
     19 栈:用于存储该线程的局部变量,这些局部变量是该线程私有的,除此之外还用来存放线程的调用栈祯。
     20 堆:是一个进程中最大的一块内存,堆是被进程中的所有线程共享的。
     21 方法区:则用来存放 NM 加载的类、常量及静态变量等信息,也是线程共享的 。
     22 
     23  
     24 进程:有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。
     25 线程:是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,
     26         但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。
     27 
     28 
     29 
     30 
     31 并行与并发:
     32 并行:多个cpu真正地处理一段逻辑,真正的同时处理
     33 并发:只是cpu调度,看上取是同时执行,但实际上并不是
     34 
     35 线程安全:
     36 一段代码:在并发情况下,经过多线程,线程的调度顺序,不影响结果-->此时多线程 安全
     37 一段代码:在并发情况下,经过多线程,线程的调度顺序,影响结果-->此时多线程 不安全    
     38 
     39         
     40 同步:Java中的同步是通过人为的控制保证->保证共享资源的多线程 称为 安全线程
     41         使用关键字synchronized 
     42 
     43 线程状态:
     44 调用join()和sleep()方法,sleep()时间结束或被打断,join()中断,IO完成都会回到Runnable状态,等待JVM的调度。
     45 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable)
     46 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable)。
     47 此外,在runnable状态的线程是处于被调度的线程,此时的调度顺序是不一定的。Thread类中的yield方法可以让一个running状态的线程转入runnable。
     48 
     49 monitor:
     50 Java中的每个对象都有一个监视器,来监测并发代码的重入。
     51     在synchronized 范围内,监视器发挥作用。
     52         在非多线程编码时该监视器不发挥作用
     53 
     54 wait/notify必须存在于synchronized块中。
     55      这三个关键字针对的是同一个监视器(某对象的监视器)
     56 当某代码并不持有监视器的使用权时去wait或notify
     57     在synchronized块中去调用另一个对象的wait/notify(因为不同对象的监视器不同)
     58         都会抛出java.lang.IllegalMonitorStateException。
     59 
     60 synchronized单独使用:
     61 代码块:synchronized (this) {....}
     62 直接用于方法: public synchronized void run() {...}
     63 
     64 
     65 volatile
     66 多线程的内存模型:main memory(主存)、working memory(线程栈)
     67     在处理数据时,线程会把值从主存load到本地栈,完成操作后再save回去
     68         (volatile关键词的作用:每次针对该变量的操作都激发一次load and save)    
     69 
     70 多线程使用的变量如果不是volatile或者final修饰的,
     71     很有可能产生不可预知的结果
     72         另一个线程修改了这个值,但是之后在某线程看到的是修改之前的值
     73 多线程是会缓存值的,线程栈 中可能有多个副本,数据可能出错
     74     本质上,volatile就是不去缓存,直接取值
     75         在线程安全的情况下加volatile会牺牲性能。
     76 
     77 Java 内存模型规定,将所有的变量都存放在主内存中,当线程使用变量时,
     78     会把主内存里面的变量复制到自己的工作空间或者叫作工作内存,
     79         线程读写变量时操作的是自己工作内存中的变量 
     80 
     81 共享变量的内存不可见问题,也就是线程B写入的值对线程A不可见。        
     82 synchronized 的内存语义:
     83 这个内存语义就可以解决共享变量内存可见性问题。
     84     进入synchronized块的内存语义 :是把在synchronized块内使用到的变量从线程的工作内存中清除,
     85         这样在synchronized块内使用到该变量时就不会从线程的工作内存中获取,而是直接从主内存中获取。
     86     退出synchronized块的内存语义:是把在synchronized块内对共享变量的修改刷新到主内存。
     87         会造成上下文切换的开销,独占锁,降低并发性
     88 Volatile([ˈvɒlətaɪl] 不稳定的)的理解:
     89 该关键字可以确保对一个变量的更新对其他线程马上可见。
     90     当一个变量被声明为volatile时,线程在写入变量时不会把值缓存在寄存器或者其他地方,而是会把值刷新回主内存。
     91         当其他线程读取该共享变量时-,会从主内存重新获取最新值,而不是使用当前线程的工作内存中的值。
     92 volatile的内存语义和synchronized有相似之处
     93 当线程写入了volatile变量值时就等价于线程退出synchronized同步块(把写入工作内存的变量值同步到主内存),
     94 读取volatile变量值时就相当于进入同步块(先清空本地内存变量值,再从主内存获取最新值)。不能保证原子性
     95 
     96 
     97 
     98 
     99 基本线程类:Thread类,Runnable接口,Callable接口
    100 Thread类:实现了Runnable接口,启动一个线程的方法:
    101         Thread thread=new Thread();
    102         thread.start();
    103 重写run方法:
    104 使用继承方式的好处是,在run()方法内获取当前线程直接使用this就可以了,
    105     无须使用Thread.currentThread()方法;
    106         不好的地方是Java不支持多继承,如果继承了Thread类,那么就不能再继承其他类。
    107             任务与代码没有分离,当多个线程执行一样的任务时需要多份任务代码。
    108 
    109 
    110 
    111 public static Thread.yield();//当前线程可转让cpu控制权,让别的就绪状态线程运行(切换)
    112 public static Thread.sleep();//暂停一段时间
    113 public join();//在一个线程中调用other.join(),将等待other执行完后才继续本线程。    
    114 public interrupte();//后两个函数皆可以被打断
    115 (中断标识值是否为true)
    116 中断是一个状态!interrupt()方法只是将这个状态置为true而已
    117 中断只会影响到wait状态、sleep状态和join状态。
    118     被打断的线程会抛出InterruptedException。
    119 Thread.interrupted()检查当前线程是否发生中断,返回boolean
    120     synchronized在获锁的过程中是不能被中断的。
    121 
    122 设置线程名称 Thread.name,并设置线程组 ThreadGroup,目的是方便管理
    123 不能用try,catch来获取线程中的异常
    124 
    125 Runnable
    126 实现Runable接口
    127 实现run方法:解决继承Thread的缺点,没有返回值
    128 
    129 Callable
    130 future模式:并发模式的一种,可以有两种形式,即无阻塞和阻塞
    131     分别是isDone和get。
    132         其中Future对象用来存放该线程的返回值以及状态
    133 
    134 ExecutorService e = Executors.newFixedThreadPool(3);
    135  //submit方法有多重参数版本,及支持callable也能够支持runnable接口类型.
    136 Future future = e.submit(new myCallable());
    137 future.isDone() //return true,false 无阻塞
    138 future.get() // return 返回值,阻塞直到该线程运行结束
    139 
    140 
    141 
    142  */
    143 public class SaleTicket implements Runnable {
    144 
    145     public int total;
    146     public int count;
    147 
    148     public SaleTicket() {
    149         total = 100;
    150         count = 0;
    151     }
    152     
    153     public void run() {
    154         while (total > 0) {
    155             synchronized (this) {//ˈsɪŋkrənaɪzd]
    156                 if (total > 0) {
    157                     try {//Thread.sleep(800);
    158                         Thread.sleep(new Random().nextInt(1000));
    159                     } catch (InterruptedException e) {
    160                         e.printStackTrace();
    161                     }
    162                     count++;
    163                     total--;
    164                     System.out.println(Thread.currentThread().getName() + "	当前票号:" + count);
    165                 }
    166             }
    167         }
    168     }
    169     
    170     //第二种方法
    171 //    private static int num = 0;
    172 //
    173 //    public static synchronized int sale() {
    174 //        int i = ++num;
    175 //        return i > 100 ? -1 : i; // 如果i>100返回-1.小于100返回i
    176 //    }
    177 //    @Override
    178 //    public void run() {
    179 //        int i = 0;
    180 //        //System.out.println(SaleTicket.num);
    181 //        while ((i = SaleTicket.sale()) != -1) {
    182 //            System.out.println("第"+Thread.currentThread().getName() + "号窗口售卖第" + i+"张票");
    183 //            try {
    184 //                Thread.sleep(100);
    185 //            } catch (InterruptedException e) {
    186 //                e.printStackTrace();
    187 //            }
    188 //
    189 //        }
    190 //    }
    191 }
     1 package org.java;
     2 
     3 public class ThreadTest {
     4 
     5     public static void main(String[] args) {
     6         SaleTicket st = new SaleTicket();
     7         //线程 实现了runnable接口,可以当作参数 传入thread,同时定义线程名字
     8         // 也可一块初始化 名字//Thread thread=new Thread(saleTicket, "1");
     9         for (int i = 1; i <= 5; i++) {
    10             new Thread(st, "售票点" + i).start();
    11         }
    12     }
    13 }
  • 相关阅读:
    CI持续集成系统环境--Gitlab+Gerrit+Jenkins完整对接
    解惑|你是否为容器监控操碎了心?
    4 使用smartcar进行仿真
    1 简单的ROS机器人仿真
    1 rbx1 Kinetic 安装和测试
    2020.4.13 Resources
    2. dwa_local_planner_params.yaml 参数意义
    robotics
    PCL 点云处理
    C++异常处理解析
  • 原文地址:https://www.cnblogs.com/NirobertEinteson/p/12029693.html
Copyright © 2020-2023  润新知