• 22 | 多线程4


    1 同步方法

    同步代码块

    2 使用Lock接口

    可以使线程的操作更加的灵活优雅,可以更加的精细的操作锁的持有和释放,可以极大的提高同步的运行效率

     
    import java.util.concurrent.ExecutorService;  
    import java.util.concurrent.Executors;  
    import java.util.concurrent.locks.Lock;  
    import java.util.concurrent.locks.ReentrantLock;  
    
    public class Test {  
        public static  void   main(String[] args) {  
            A a=new A();  
            Thread t=new  Thread(new Thread1(a));  
            ExecutorService  pool=Executors.newFixedThreadPool(2);  
            pool.execute(t);  
            pool.execute(t);  
            pool.shutdown();  
        }  
    }  
     //同步方法  
    //class A {  
    //  public synchronized void test(String name) {  
    //       System.out.println(name);  
    //       try {  
    //          Thread.sleep(1000);  
    //      } catch (InterruptedException e) {  
    //          // TODO Auto-generated catch block  
    //          e.printStackTrace();  
    //      }  
    //  }     
    //}  
      
    class A {  
    private Lock lock1=new ReentrantLock();  
    private Lock lock2=new ReentrantLock();  
    public  void test1(String name) {  
             lock1.lock(); //持锁  
             System.out.println("持锁线程1:"+name);  
             lock2.lock(); //持锁  
             System.out.println("持锁线程2:"+name);  
             try {  
                 Thread.sleep(2000);  
                 lock1.unlock(); //释放锁  
                 System.out.println("释放锁1:"+name);  
                 lock2.unlock(); //释放锁  
                 System.out.println("释放锁2:"+name);  
             } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
             }  
       }  
    public  void test(String name) {  
            synchronized(this) {  
            System.out.println(name);  
                try {  
                    Thread.sleep(2000);  
                } catch (InterruptedException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
            }  
         }  
       }  
    }  
    class Thread1 implements Runnable{  
        private final A a;  
        public Thread1(final  A a) {  
            this.a=a;  
        }  
         @Override  
         public void run() {  
                  this.a.test1(Thread.currentThread().getName());  
         }  
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    3 IO流阻塞和运算阻塞

    3.1 IO流阻塞

    对于数据进行读写或者其他的IO操作,这种情况下,可以竟可能的划分更多的线程

    3.2 运算阻塞

    在数据的运算过程当中,CPU是不会释放资源的;这种情况下,我们线程的划分最大的数量就是CPU的内核数量

    3.3 大数据

    大数据当中的流式计算:把运算阻塞变成是IO流阻塞

    4 重入锁/读写锁

    • 当多个线程同时访问读锁时,不受影响,可以同时访问;
    • 当某个线程获得写锁时,其他线程级不能读,也不能写,写锁属于排他/独占锁。

    三个特性

    A、获取锁的模式有两种

    1)公平锁:不存在饥饿状态的线程,所有线程有会得到公平的执行几率,运行效率相对低一些
    2)非公平锁:(默认)在某种极端情况下,会出现某个或者某几个线程始终处于饥饿状态

    B、重进入
    某个线程,同一时刻,可以持有多个锁

    1)锁的降级:写锁的强度要高于读锁,遵循获取写锁,获取读锁在释放写锁的次序,写锁能够降级成为读锁
    2)锁只有降级,没有升级,因为写锁时独占锁,而读锁时非独占锁

    C、信号重:当信号量未达到上限时,可以正常执行,而超过上限,则线程进入阻塞
    D、阻塞队列和阻塞栈

    1)队列是一个单向通道
    2)栈是一个双向通道
    3)超出上限以后,进入阻塞
    4)超出上限以后,返回false
    5)没有元素,进入阻塞
    6)没有元素,返回null

    E、条件变量

    1)在持锁的情况下,可以等待和唤醒
    2)可以实现对对象同时唤醒

    import java.util.concurrent.locks.Condition;  
    import java.util.concurrent.locks.Lock;  
    import java.util.concurrent.locks.ReentrantLock;  
    import java.util.concurrent.locks.ReentrantReadWriteLock;  
    public class Test2 {  
        public static  void   main(String[] args) throws Exception {  
              Lock lock=new ReentrantLock();       
              Condition c1=lock.newCondition();           
        }  
    }  
    class A{  
           private Lock lock;  
           private Condition c;  
           public  A(Lock lock,Condition c) {   
               this.lock=lock;  
               this.c=c;  
           }  
           public void test() {  
               lock.lock();  
               try {              
               c.await();  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
               lock.unlock();  
           }  
    }  
    class B{  
           private Lock lock;  
           private Condition c;  
           public  B(Lock lock,Condition c) {   
               this.lock=lock;  
               this.c=c;  
           }  
           public void test() {  
               lock.lock();  
               try {  
                c.await(); //等待  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
               lock.unlock();  
           }        
    }  
    class C{  
          private Lock lock;  
           private Condition c;  
           public  C(Lock lock,Condition c) {   
               this.lock=lock;  
              this.c=c;  
          }  
           public void test() {  
               lock.lock();  
              c.signalAll(); //唤醒  
               lock.unlock();  
           }  
    }  
    class Thread1 implements  Runnable{  
        private final Condition c1;  
        public Thread1(final Condition c1) {  
               this.c1=c1;  
        }  
        @Override  
        public void run() {  
             try {  
                Thread.sleep(2000);  
                this.c1.signalAll();  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
     }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    F、原子量

    1)即便是原子量,依然要做的线程同步
    2)保证多个线程对同一个数据的可见性和线程安全性

    G、障碍器

    1)有若干子任务需要执行,某个线程需要等到所有的子任务全部完成后,在执行,这时需要使用障碍器
    2)在子线程通知完障碍器,主线程执行完毕后,子线程还将继续执行没执行完的内容

    H、线程池在面试当中属于一个问的比较频繁的

  • 相关阅读:
    自己本地写完代码后,不要直接git pull拉远程代码,会导致代码丢失
    家居建材如何在线管理订单?数商云采购系统实现订单发收货、退换货流程化管控
    Hadoop
    【Linux入门】— 腾讯云服务器的搭建
    「MobileNet V3」70 个犬种的图片分类
    Jmeter 分布式压测,你的系统能否承受高负载?
    《Head First HTML5 javascript》第3章 探索浏览器 知识点总结
    PCycDB:全面准确的磷循环基因分析数据库
    思科大作业
    for循环中var声明导致定时器输出奇特现象的粗略解释
  • 原文地址:https://blog.csdn.net/u013916029/article/details/126258219