• java保证多线程的执行顺序


    1. java多线程环境中,如何保证多个线程按指定的顺序执行呢?

    1.1 通过thread的join方法保证多线程的顺序执行, wait是让主线程等待

    比如一个main方法里面先后运行thread1,,thread2,thread3,那么thread1.start()之后,运行thread1.join(),这是会让主线程mian等待新的线程thread1执行完了,再执行主线程mian下面的代码,thread1.join()是然主线程main wait。

    package com.java.yj;
    
    /**
     * Created by yejian on 2018/7/9.
     */
    public class MultiThread {
        public static void main(String[] args) throws InterruptedException {
            Thread thread1 = new Thread(new Thread1());
            thread1.start();
            thread1.join();
            Thread thread2 = new Thread(new Thread2());
            thread2.start();
            thread2.join();
            Thread thread3 = new Thread(new Thread3());
            thread3.start();
    
        }
    
        public static class Thread1 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread1");
            }
        }
    
        public static class Thread2 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread2");
            }
        }
    
        public static class Thread3 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread3");
            }
        }
    
    }
    
    

    1.2 ExecutorService executor = Executors.newSingleThreadExecutor()

    java5以后提供的一个多线程操作方法,创建一个只有一个线程的线程池操作,会创建一个线程队列,按FIFO的顺序执行里面的线程。

    package com.java.yj;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * Created by yejian on 2018/7/9.
     */
    public class MultiThread2 {
        public static void main(String[] args) throws InterruptedException {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.submit(new Thread1());
            executor.submit(new Thread2());
            executor.submit(new Thread3());
            executor.shutdown();
        }
    
        public static class Thread1 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread1");
            }
        }
    
        public static class Thread2 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread2");
            }
        }
    
        public static class Thread3 implements Runnable{
            @Override
            public void run() {
                System.out.println("Thread3");
            }
        }
    
    
    }
    
    

    2. java中的volatile和synthronized

    2.1JMM-java memory model

    解决并发过程中如何处理可见性,原子性,有序性的问题
    runnable ,thread。
    并发编程中的2个关键问题:
    a. 线程间如何通信 --wait() notify() notifyAll()
    a) 共享内存 -隐式通信
    b) 消息传递 - 显示通信
    b. 线程之间如何同步
    在共享内存的并发模型中,同步是显示做的; synchronized
    在消息传递的并发模型中,由于小时发送必须在消息接受之前,所以同步是隐式的

    2.2. 定位内存可见性问题

    什么对象是内存共享的 ,什么不是,堆内存的对象,java虚拟机栈
    

    JMM定义了线程和主内存之间的一个关系。线程之间通讯,必须通过主内存通讯。

    volatile、synchronized
    volatile 功能,声明了volatile的变量,进行写操作的时候,jvm会向处理器发送一条Lock的前缀指令,会把这个变量所在缓存行的数据写回到系统内存。
    在多处理器的情况下,保证各个处理器缓存一致性的特点,会实现缓存一致性协议。改变了值的volatile变量,在其他行程被指为失效状态其他线程要使用这个变量,需要重新到驻村里面去取。

    synchronized:可重入锁、互斥性、可见性
    volatile 可以做到原子性,可见性,不能做到复合操作的原子性

    比如: volatile int i;
    i++ 读取i的值,给i加1,把新的值赋值给i,这个i++操作在多线程环境下是无法保证原子性的

    synchronized后面锁定的对象,可以是一个类对象,也可以是一个成员变量。
    第一个线程进来调用monitorener 和monitorexit实现,获取对象的监视器,释放对象监视器
    后续进程过来,如果monitor还没有释放,那么他获取不到这个对象的monitor,会放到一个对列里面:synthronizedQueue。 等到对象的锁释放了,通知synthronizedQueue出队列,获取那个monitor。

    3. Lock和synchronized

    Lock是java5以后出现的,在juc包: java.util.concurrentlocks

    3.1 synthronized的锁什么时候释放

        1.1 获取锁的线程执行完了该代码块
        1.2 线程出现异常
    

    3.2 synchronized的缺陷

    2.1 读写冲突
    

    3.3 Lock可以主动去释放锁,而synchronized是被动的

    ReadWriteLock
    ReadLock
    WriteLock
    ReenterantLock可重入锁
    可中断锁
    公平锁 等待一个锁的实际越长,获取这个锁的几率越高
    ReenterantReadWriteLock 可重入读写锁
    Lock是java里面的一个接口,有丰富的实现,而synchronized是java的一个关键字,是一个内置的功能

    竞争资源激烈的情况,Lock性能优于synchronized,但是jdk7,8对synchronized做了很多优化,性能差异不大。

  • 相关阅读:
    【百度之星2014~初赛(第二轮)解题报告】Chess
    Cocos2d-x3.0游戏实例之《别救我》第二篇——创建物理世界
    【CSS】使用CSS控制文字过多自动省略号
    【jar】JDK将单个的java文件打包为jar包,并引用到项目中使用【MD5加密】
    【JSP EL】el表达式判断是否为null
    【redis】5.spring boot项目中,直接在spring data jpa的Repository层使用redis +redis注解@Cacheable直接在Repository层使用,报错问题处理Null key returned for cache operation
    【Exception】查看异常出现在具体的文件名/类名/方法名/具体行号
    【bootstrap】使用支持bootstrap的时间插件daterangepicker
    【css】设置div位于浏览器的最底层,离用户最远
    【前台】【单页跳转】整个项目实现单页面跳转,抛弃iframe
  • 原文地址:https://www.cnblogs.com/james0/p/9280144.html
Copyright © 2020-2023  润新知