Java基础 ——线程

打印 上一主题 下一主题

主题 1041|帖子 1041|积分 3123

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
多线程

并行和并发


  • 需求:边打好汉联盟和边听音乐
  • 问题:只能先后关系,并不能同时发生

    • 多进程或者多线程来办理

  • 并行和并发:

    • 并行:多件事变在同一时候发生
    • 并发:多件事变在同一时间段发生,同一时间段多个程序同时运行

  • 单个CPU:一个时间点只能执行一个程序,多个程序可以交替执行。
  • 线程调理:多个线程以某个顺序执行
进程与线程


  • 进程:内存中的应用程序,每个进程有一块独立的内存空间,一个应用程序可以同时启用多个进程,有独立内存空间,至少有一个线程
  • 线程:进程中的执行任务单元,一个进程里面可以拥有多个线程,栈空间独立,堆内存共享
  • 多线程的优势:因为堆内存是共享的,以是内存的开销是不是较少。
  • 多线程具体运行谁人线程,取决于 CPU调理
  • java 程序中最少有几个线程:

    • 主线程
    • GC垃圾接纳线程

  • 线程的调理:JVM 接纳抢占式的调理方式,没有接纳分时概念,谁抢到谁执行。
  • 多线程的应用:

    • 抢票
    • 游戏
    • 多线程下载

  • 宽带带宽:以位(bit)计算的,下载速度以字节(byte),1字节=8位

    • 1024KB/s 代表 1M,下载速度,1024/8 128KB/s

多线程实现方式


  • 继承 Thread 类

    • 重写 run 方法
      1. public class MusicDemo extends Thread{
      2.     @Override
      3.     public void run() {
      4.         for (int i = 0; i < 10; i++) {
      5.             System.out.println("听音乐:"+i);
      6.         }
      7.     }
      8. }
      复制代码
    • 启动线程,调用 start 方法
      1. MusicDemo musicDemo = new MusicDemo();
      2. musicDemo.start();
      复制代码
    • 注意:不要去调用 run() 方法

  • 实现 Runnable 接口

    • 实现Runnable 接口,实现 Run 方法
      1. public class PlayGame implements Runnable {
      2.     @Override
      3.     public void run() {
      4.         for (int i = 0; i < 10; i++) {
      5.             System.out.println("打游戏:" + i);
      6.         }
      7.     }
      8. }
      复制代码
    • 启动(先创建对象,再创建 Thread 对象通过构造器获得线程对象)
      1. PlayGame playGame = new PlayGame();
      2. Thread thread = new Thread(playGame);
      3. thread.start();
      复制代码

  • 使用匿名内部类来创建线程(只适用于只使用一次的方式)
    1. new Thread(new Runnable() {
    2.             @Override
    3.             public void run() {
    4.                 for (int i = 0; i < 10; i++) {
    5.                     System.out.println("统计人头数:" + i);
    6.                 }
    7.             }
    8.         }).start();
    复制代码
线程的调理


  • 线程控制操作:Thread.sleep(1000L);
  • 线程合并(团结线程):

    • join方法(操作线程先执行完之后,等候线程才执行)

  • 保卫线程:GC 使用

    • 目的:为别的线程服务的—GC—
    • 特点:主线程竣事,保卫线程就竣事
    • 创建线程:默认是前台线程
    • 获取保卫线程thread.setDaemon(true),必须再 start() 方法之前

  • 获取当前线程及其名称

    • Thread t = Thread.currentThread();
    • t.getName();

  • 线程设置优先级

    • 注意:优先级高,只不过是获取执行机会更大(取决于CPU调理)
      1. /**
      2. * The minimum priority that a thread can have.
      3. */
      4. public final static int MIN_PRIORITY = 1;
      5. /**
      6. * The default priority that is assigned to a thread.
      7. */
      8. public final static int NORM_PRIORITY = 5;
      9. /**
      10. * The maximum priority that a thread can have.
      11. */
      12. public final static int MAX_PRIORITY = 10;
      复制代码

  • 线程的让位:

    • yield 方法:当前线程对象去提示CPU调理器本身愿意让出CPU资源(但是调理器可以忽略你的哀求)
    • sleep 和 yield 方法的区别

      • 都能使当前处于运行状态的线程临时放弃 cpu 把机会给别的线程
      • sleep 方法给别的线程运行机会,但是不考虑别的线程的优先级,yield 只会给相同优先级,或者更高优先级的线程运行机会
      • 调用 sleep 方法之后,线程进入计时等候状态,yield 进入停当状态


线程同步


  • 需求:猴子(3个 A B C)吃香蕉30个,使用多线程的方式实现

    • 继承 Thread 类的方式

      • 同一个编号的香蕉被多个猴子吃
        1. public class MonkeyDemo extends Thread {
        2.     private int num = 30;//香蕉总数
        3.     @Override
        4.     public void run() {
        5.         for (int i = 0; i < 30; i++) {
        6.             if (num > 0) {
        7.                 System.out.println(super.getName() + "吃了编号为:" + num-- + "的香蕉");
        8.             }
        9.         }
        10.     }
        11. }
        12. MonkeyDemo monkeyA = new MonkeyDemo();
        13. monkeyA.setName("A");
        14. MonkeyDemo monkeyB = new MonkeyDemo();
        15. monkeyB.setName("B");
        16. MonkeyDemo monkeyC = new MonkeyDemo();
        17. monkeyC.setName("C");
        18. monkeyA.start();
        19. monkeyB.start();
        20. monkeyC.start();}}
        复制代码

    • 实现 Runnable 接口

      • 是否可以共享同一个资源的缘故原由,实现方式可以做到(当有网络耽误的时候,也不可以做到)
      1. public class MonkeyRunnable implements Runnable{
      2.     private int num = 30;
      3.     @Override
      4.     public void run() {
      5.         for (int i = 0; i < 30; i++) {
      6.             if (num > 0) {
      7.                 System.out.println(Thread.currentThread().getName() + "吃了编号为:" + num-- + "的香蕉");
      8.             }
      9.         }
      10.     }
      11. }
      12. MonkeyRunnable runnable = new MonkeyRunnable();
      13. new Thread(runnable,"A").start();
      14. new Thread(runnable,"B").start();
      15. new Thread(runnable,"C").start();
      复制代码


  • 办理多个猴子不能同时吃到同一个香蕉的案例

    • 同步代码块

      • 语法
      • 非静态
      • 同步锁是谁?

        • 非静态的来说,同步锁就是 this
        • 静态的来说,类的字节对象(MonkeyRunnable.class)
        1. synchronized(同步锁){
        2. }
        复制代码

      • 为了保证每个线程都可以或许正常执行,原子操作,一般的,把当前并发访问的共同资源作为同步监听对象
      • 任何时候,只能运行一个线程拥有同步锁,谁拿到谁执行,别的的等候
      • 不要使用同步锁去修饰 run 方法,修饰之后,某一个线程执行完了别的的才可以执行

    • 同步方法
      1. synchronized public void eat() {
      2.     //业务逻辑
      3. }
      复制代码
    • 锁机制(Lock):
      1. Lock lock = new ReentrantLock();
      2. //上锁
      3. lock.lock();
      4.         if (num > 0) {
      5.             System.out.println(Thread.currentThread().getName() + "吃了编号为:" + num-- + "的香蕉");
      6.         }
      7. //解锁
      8. lock.unlock();
      复制代码

  • 同步代码块,同步方法,同步锁如何选用?

    • 只管淘汰锁的作用域(Synchronized)
    • 发起使用锁机制(很好的去控制锁的作用范围,性能更高)


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

河曲智叟

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表