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方法的区别 ?

  • 相关阅读:
    POJ-1189 钉子和小球(动态规划)
    POJ-1191-棋盘分割(动态规划)
    Java实现 LeetCode 730 统计不同回文子字符串(动态规划)
    Java实现 LeetCode 730 统计不同回文子字符串(动态规划)
    Java实现 LeetCode 729 我的日程安排表 I(二叉树)
    Java实现 LeetCode 729 我的日程安排表 I(二叉树)
    Java实现 LeetCode 729 我的日程安排表 I(二叉树)
    Java实现 LeetCode 728 自除数(暴力)
    Java实现 LeetCode 728 自除数(暴力)
    Java实现 LeetCode 728 自除数(暴力)
  • 原文地址:https://www.cnblogs.com/padazala/p/12650387.html
Copyright © 2011-2022 走看看