多线程学习笔记一

关于线程的常见问题-

  • 什么是并发与并行?

    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

猜你喜欢

转载自www.cnblogs.com/padazala/p/12650387.html