zoukankan      html  css  js  c++  java
  • 多线程学习笔记一

    关于线程的常见问题-

    • 什么是并发与并行?

      1. 并行:两个或者多个事件在同一时刻发生
      2. 并发:两个或者多个事件在同一个时间段内发生
    • 什么是进程与线程?

      1. 进程是正在运行的程序的实例
      2. 进程是线程的容器,一个进程可以开启多个线程
      3. 比如打开一个浏览器,会创建进程
    • 线程如何创建?

      1. 继承Thread类
      2. 实现Runnable接口
      3. 实现Callable接口鸭
      4. 从线程池-Excutor 获取线程
    • 实现类接口和继承类接口的比较:
    1.   接口更适合多个相同的程序代码去共享同一个资源
    2.   接口可以避免java中单继承的局限性
    3.   接口代码可以被多个线程共享,代码和线程独立
    4.   线程池只能 放入实现Runnable和Callable接口的线程,不能直接放入继承Thread的线程
    5.   java中,每次运行程序至少启动2个线程,一个是main线程,一个是垃圾收集线程
    • 线程的生命周期?

     

    • 什么是线程安全问题?线程安全问题解决方案?
      • 线程安全问题都是由全局变量及静态变量引起的
      • 若每个线程对全局变量,静态变量只读,不写,则这个变量是线程安全的
      • 若有多个线程同时执行写操作,则需要考虑线程同步,否则就可能影响线程安全

        

      •  解决方案 :线程同步 - 只要在某个线程修改共享资源的时候,其他线程不能修改该资源,等待修改完毕同步之后,才能去抢夺资源,完成对应的操作,保证了数据的同步性。
      •  java引入了7种同步机制:
        • 同步代码块(synchronized)
        • 同步方法(synchronized)
        • 同步锁(ReentrantLock)
        • 特殊域变量(volatile)
        • 局部变量(ThreadLocal)
        • 阻塞队列(LinkedBlockingQueue)
        • 原子变量(Atomic*)

     

    • 什么是线程死锁?死锁的必要条件?如何避免死锁?

      

     

    • 线程如何通讯?
      • 多线程并发执行时,在默认情况下cpu是随机切换的,有时我们希望cpu按我们的规律执行线程,此时就需要线程之间的协调通信

      •  notify() & wait() 方法切换线程示例打印奇数偶数:
        •   
           1 public class ThreadTCPDemo {
           2     private int i = 0;
           3     private Object obj = new Object();
           4 
           5     public void odd() {
           6         // 判断是否小于10
           7         while (i < 10) {
           8             synchronized (obj) {
           9                 // 打印奇数
          10                 if (i % 2 == 1) {
          11                     System.out.println("奇数:" + i);
          12                     i++;
          13                     obj.notify(); // 唤醒偶数线程打印
          14                 } else {
          15                     try {
          16                         obj.wait(); // 等待偶数线程打印完毕
          17                     } catch (Exception e) {
          18                         e.printStackTrace();
          19                     }
          20                 }
          21             }
          22         }
          23     }
          24     public void even() {
          25         // 判断是否小于10
          26         while (i < 10) {
          27             synchronized (obj) {
          28                 // 打印奇数
          29                 if (i % 2 == 0) {
          30                     System.out.println("偶数:" + i);
          31                     i++;
          32                     obj.notify(); // 唤醒奇数线程打印
          33                 } else {
          34                     try {
          35                         obj.wait(); // 等待奇数线程打印完毕
          36                     } catch (Exception e) {
          37                         e.printStackTrace();
          38                     }
          39                 }
          40             }
          41         }
          42     }
          43     public static void main(String[] args) {
          44         final ThreadTCPDemo threadTCPDemo = new ThreadTCPDemo();
          45 
          46         Thread thread = new Thread(new Runnable() {
          47             @Override
          48             public void run() {
          49                 threadTCPDemo.odd();
          50             }
          51         });
          52         Thread thread2 = new Thread(new Runnable() {
          53             @Override
          54             public void run() {
          55                 threadTCPDemo.even();
          56             }
          57         });
          58         thread.start();
          59         thread2.start();
          60     }
          61 }
          View Code
      •  Condition 的signal()&await()方法切换线程示例打印奇数偶数:
        •   
           1 public class ThreadTCPDemo {
           2     private int i = 0;
           3     // private Object obj = new Object();
           4     private Lock lock = new ReentrantLock(false);
           5     private Condition condition = lock.newCondition();
           6 
           7     public void odd() {
           8         // 判断是否小于10
           9         while (i < 10) {
          10             lock.lock();  // 加锁
          11             try {
          12                 // 打印奇数
          13                 if (i % 2 == 1) {
          14                     System.out.println("奇数:" + i);
          15                     i++;
          16                     condition.signal(); // 唤醒偶数线程打印
          17                 } else {
          18                     try {
          19                         condition.await(); // 等待偶数线程打印完毕
          20                     } catch (Exception e) {
          21                         e.printStackTrace();
          22                     }
          23                 }
          24             } catch (Exception e) {
          25                 e.printStackTrace();
          26             } finally {
          27                 lock.unlock();
          28             }
          29         }
          30     }
          31 
          32     public void even() {
          33         // 判断是否小于10
          34         while (i < 10) {
          35             lock.lock();
          36             try {
          37                 // 打印偶数
          38                 if (i % 2 == 0) {
          39                     System.out.println("偶数:" + i);
          40                     i++;
          41                     condition.signal(); // 唤醒奇数线程打印
          42                 } else {
          43                     try {
          44                         condition.await(); // 等待奇数线程打印完毕
          45                     } catch (Exception e) {
          46                         e.printStackTrace();
          47                     }
          48                 }
          49             } catch (Exception e) {
          50                 e.printStackTrace();
          51             } finally {
          52                 lock.unlock();
          53             }
          54         }
          55     }
          56 
          57     public static void main(String[] args) {
          58         final ThreadTCPDemo threadTCPDemo = new ThreadTCPDemo();
          59 
          60         Thread thread = new Thread(new Runnable() {
          61             @Override
          62             public void run() {
          63                 threadTCPDemo.odd();
          64             }
          65         });
          66         Thread thread2 = new Thread(new Runnable() {
          67             @Override
          68             public void run() {
          69                 threadTCPDemo.even();
          70             }
          71         });
          72         thread.start();
          73         thread2.start();
          74     }
          75 }
          View Code 
      •  CountDownLatch 示例:
          
     1 public class CoachRacerDemo {
     2     // 设置要等待的运动员是3个
     3     private CountDownLatch countDownLatch = new CountDownLatch(3);
     4 
     5     /**
     6      *运动员方法,由运动员线程调用
     7      */
     8     public void racer(){
     9         // 获取运动员线程名称
    10         String name = Thread.currentThread().getName();
    11         // 运动员开始准备:打印准备信息
    12         System.out.println(name+"正在准备。。。");
    13         // 线程休眠1000毫秒,表示运动员在准备
    14         try {
    15             Thread.sleep(1000);
    16         }catch (Exception e){
    17             e.printStackTrace();
    18         }
    19         // 运动员准备完成
    20         System.out.println(name+" 准备完毕!");
    21         countDownLatch.countDown();
    22     }
    23 
    24     /**
    25      * 教练方法
    26      */
    27     public void coach() {
    28         // 教练线程名称
    29         String name = Thread.currentThread().getName();
    30         // 教练等待所有的运动员准备完毕,打印等待信息
    31         System.out.println(name+" 教练准备完毕。。。");
    32         // 调用countDownLatch的await方法等待其他线程执行完毕
    33         try {
    34             countDownLatch.await();
    35         }catch (Exception e){
    36             e.printStackTrace();
    37         }
    38         // 所有运动员已就绪,教练开始训练,打印训练信息
    39         System.out.println("所有运动员准备就绪,教练开始训练!");
    40     }
    41 
    42     public static void main(String[] args) {
    43 
    44         // 创建运动员实例
    45        final CoachRacerDemo coachRacerDemo =new CoachRacerDemo();
    46         // 创建三个运动员线程对象
    47         Thread thread1 = new Thread(new Runnable() {
    48             @Override
    49             public void run() {
    50                 coachRacerDemo.racer();
    51             }
    52         },"运动员1");
    53 
    54         Thread thread2 = new Thread(new Runnable() {
    55             @Override
    56             public void run() {
    57                 coachRacerDemo.racer();
    58             }
    59         },"运动员2");
    60 
    61         Thread thread3 = new Thread(new Runnable() {
    62             @Override
    63             public void run() {
    64                 coachRacerDemo.racer();
    65             }
    66         },"运动员3");
    67 
    68         // 创建教练线程
    69         Thread thread4 = new Thread(new Runnable() {
    70             @Override
    71             public void run() {
    72                 coachRacerDemo.coach();
    73             }
    74         },"教练");
    75         thread1.start();
    76         thread2.start();
    77         thread3.start();
    78         thread4.start();
    79     }
    80 }
    View Code
      •  CyclicBarrier 示例:
     1 public class ThreadCyclic {
     2     private CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
     3     public void startThread(){
     4         // 打印线程名称准备启动。。。
     5         String name = Thread.currentThread().getName();
     6         System.out.println(name+" 正在启动。。。");
     7         // 调用CyclicBarrier的await()方法等所有线程准备完成
     8         try {
     9             cyclicBarrier.await();
    10         } catch (InterruptedException e) {
    11             e.printStackTrace();
    12         } catch (BrokenBarrierException e) {
    13             e.printStackTrace();
    14         }
    15         // 打印启动信息
    16         System.out.println(name+" 启动完毕。。。");
    17     }
    18     public static void main(String[] args) {
    19         final ThreadCyclic threadCyclic = new ThreadCyclic();
    20 
    21         Thread thread =new Thread(new Runnable() {
    22             @Override
    23             public void run() {
    24                 threadCyclic.startThread();
    25             }
    26         },"thread1");
    27         Thread thread2 =new Thread(new Runnable() {
    28             @Override
    29             public void run() {
    30                 threadCyclic.startThread();
    31             }
    32         },"thread2");
    33         Thread thread3 =new Thread(new Runnable() {
    34             @Override
    35             public void run() {
    36                 threadCyclic.startThread();
    37             }
    38         },"thread3");
    39         thread.start();
    40         thread2.start();
    41         thread3.start();
    42     }
    43 }
    View Code
      • Semaphore 示例(工人使用机器):   

      •  1 / 场景: 工人使用3台机器工作,机器为互斥资源(即每次只能一个人使用)
         2 public class SemaphoreTest {
         3 
         4    static class Work implements Runnable{
         5         private int workerNo; // 工人工号
         6         private Semaphore semaphore;  // 机器数
         7 
         8        public Work(int workerNo, Semaphore semaphore) {
         9            this.workerNo = workerNo;
        10            this.semaphore = semaphore;
        11        }
        12        @Override
        13        public void run() {
        14 
        15            try{
        16                // 1. 工人获取机器
        17                semaphore.acquire();
        18                String name = Thread.currentThread().getName();
        19                // 2. 打印工人获取到机器,开始工作
        20                System.out.println(name+" - 获取到机器开始工作。。。");
        21                // 3. 给线程睡眠1秒,模拟工人使用机器
        22                Thread.sleep(1000);
        23                // 4. 使用完毕释放机器,打印工人使用完毕,释放机器
        24                System.out.println(name+" - 使用完毕,释放机器!");
        25                semaphore.release();
        26            }catch (Exception e){
        27                e.printStackTrace();
        28            }
        29 
        30        }
        31    }
        32     public static void main(String[] args) {
        33        int workers = 8;
        34        Semaphore semaphore = new Semaphore(3);
        35        for (int i=0;i<workers;i++){
        36         new Thread(new Work(i, semaphore),"工人"+i).start();
        37        }
        38     }
        39 }
        View Code

    面试题 : sleep 和wait方法的区别 ?

    面试题 : notify 和wait方法的区别 ?

  • 相关阅读:
    Poj2033
    CodeForces 540
    CodeForces 548
    LeetCode#2 Add Two Numbers
    CodeForces 544A
    POJ 2431Expedition
    HLG1116-选美大赛
    清华学堂 列车调度(Train)
    清华学堂 LightHouse
    清华学堂 Range
  • 原文地址:https://www.cnblogs.com/padazala/p/12650387.html
Copyright © 2011-2022 走看看