Javase --- 多线程复习

Java 多线程

程序

静态文件 程序 启动以后以 进程方式在 操作系统驻留

进程 (可以看见)

  • 程序运行过程中 在操作系统内存中一个一个的实例。
  • 进程之间 独立存储 独立管理的 彼此是隔离的。
  • 程序 在 运行过程 中 至少有一个 进程与之对应 取决于 设计方式
  • 进程启动 默认 会启动一个 主线程(决定进程的生死 主线程死 进程死 主线程生 进程生)。

总结 :

  • 程序 执行进入内存运行,变为一个进程
  • 进程间的资源(内存、文件····)是彼此隔离的,其他进程不允许访问(读取和写入)的。

线程 (看不见)

eg :

  • 迅雷 多线程下载软件

概念 :

  • 线程 是 进程内的一个 “基本任务”,每个线程都有自己的功能, 是 CPU 分配和调度的基本单位
  • 一个进程内可以包含多个线程 , 一个线程只能隶属于一个进程
  • 进程内至少拥有一个 线程 这个线程叫做 主线程 主线程消亡 进程 结束。

CPU、进程、线程

单核 CPU

时间片(cpu 一段的执行时间 以 纳秒 为单位)
时间片 分配给 某个线程 ----> 某个线程 来执行
这种情况 叫并发执行。

多核
  • 一个线程 在同一时间 只能拥有一个 CPU 的时间片
  • 而 多个线程 在不同时间 可以 拥有不同 CPU 的时间片

这就有了 并行 执行

Java 中的 进程 与 线程

Java 最简单程序的进程 包含 main 主线程 和 垃圾收集线程(没有关注你呢)

线程创建的三种方式

Thread (不推荐使用 Java 对 继承不友好)

package nuc.zm.MoreThread.create_thread;

import nuc.zm.io.ObjectIOTest.Object;

/**
 * demo1
 * @description 创建线程的方式 1
 * @author zm
 * @date 2022/10/15
 */
public class Demo1 {


    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        for (int i = 0; i < 10; i++) {
            System.out.println("不会出现争夺资源的main" + i);
        }
        Thread thread = Thread.currentThread();
        thread.setName("主线程");
//        让子线程先启动 才会出现 和主线程抢夺资源的情况hh
        testThread.setName("子线程");
        testThread.start();

        for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName() + i);
        }

    }

      static class TestThread extends Thread {
          /**
           * 运行
           * 线程对象 争抢资源的任务 必须放在 run 方法中
           */
          @Override
          public void run() {
              super.run();
              for (int i = 0; i < 10; i++) {
                  System.out.println(getName()  + " ==== " + i);
              }
          }
      }
}

Runnable (Java编程友好 单无法返回执行后的数据)

package nuc.zm.MoreThread.create_thread;

/**
 * 以及接下来
 * 实现 Runnable 接口 成为线程类
 * @author zm
 * @date 2022/10/16
 */
public class Demo2 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "====" + i);
        }
    }

//   main 线程 启动器
    public static void main(String[] args) {
        Demo2 demo2 = new Demo2();
        Thread thread = new Thread(demo2);
        thread.setName("子线程~~");
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "========" + i);
        }
    }
}

Callable (涉及到线程池 且线程方法具有返回值 但编程显复杂)

package nuc.zm.MoreThread.create_thread;

import java.util.Random;
import java.util.concurrent.*;

/**
 * 可调用测试
 *
 * @author zm
 * @date 2022/11/06
 */
public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
    }

    static class ThreadTest implements Callable<Integer> {
        private String name;

        @Override
        public Integer call() throws Exception {
            int speed = new Random().nextInt(10);
            int result = 0;
            for (int i = 1; i < 10; i++) {
                Thread.sleep(1000);
                result = i * speed;
                System.out.println("第 " + i + " 秒 " + this.name + " 已经跑到  " + result + " 米 " + " 速度 " + speed + " 米/秒 ");
            }
            return result;
        }

        public void start() throws ExecutionException, InterruptedException {
//        线程池
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            ThreadTest threadTest = new ThreadTest();
            threadTest.name = "参赛者A";
            ThreadTest threadTest1 = new ThreadTest();
            threadTest1.name = "参赛者B";
            ThreadTest threadTest2 = new ThreadTest();
            threadTest2.name = "参赛者C";
            Future<Integer> submit = executorService.submit(threadTest);
            Future<Integer> submit1 = executorService.submit(threadTest1);
            Future<Integer> submit2 = executorService.submit(threadTest2);
            executorService.shutdown();
            System.out.println(threadTest.name + "跑了" + submit.get() + "米");
            System.out.println(threadTest1.name + "跑了" + submit1.get() + "米");
            System.out.println(threadTest2.name + "跑了" + submit2.get() + "米");

        }
    }


}

package nuc.zm.MoreThread.create_thread;

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * demo3
 * 实现 callable 接口
 * @author zm
 * @date 2022/10/16
 */
public class Demo3 implements Callable<Double> {
    /**
     * 调用
     * 抛 子类 异常
     * @return {@link Double}
     */
    @Override
    public Double call() {
        return (double) new Random().nextInt(10);
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Demo3 demo3 = new Demo3();
        FutureTask<Double> futureTask = new FutureTask<>(demo3);
        Thread thread = new Thread(futureTask);
        thread.start();
        Object o = futureTask.get();
        System.out.println(o);
    }
}

线程 同步问题

现实案例 : 抛绣球案例 很多人争抢一个绣球(资源)

synchronized(同步锁)

作用 : 利用一个特定的对象设置一个锁 , 在 多线程 并发访问的时候,同时只允许一个线程 获得这个锁,并执行特定代码。
执行后 会释放锁, 继续和其他线程争抢资源。

所有线程都访问 同一个打印方法 就会出现 线程安全问题

package nuc.zm.MoreThread;

/**
 * 同步采样
 * 演示 同步锁
 * @author zm
 * @date 2022/11/06
 */
public class SyncSample {
    static class Printer {
        public void print() {
            try {
                Thread.sleep(500);
                System.out.print("你");
                Thread.sleep(500);
                System.out.print("好");
                Thread.sleep(500);
                System.out.print("世");
                Thread.sleep(500);
                System.out.print("界");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
    public void start() {
        Printer printer = new Printer();
        for (int i = 0; i < 10; i++) {
            PrintTask printTask = new PrintTask();
            printTask.printer = printer;
            Thread thread = new Thread(printTask);
            thread.start();
        }

    }
    static class PrintTask implements Runnable {
        private  Printer printer;
        @Override
        public void run() {
            printer.print();
        }
    }
    public static void main(String[] args) {
        new SyncSample().start();
    }
}

解决 加锁

synchronized 代码块 – 任意对象
synchronized 方法 – this 当前对象
synchronized 静态方法 – 该类的字节码对象

package nuc.zm.MoreThread;

import java.util.concurrent.locks.Lock;

/**
 * 同步采样
 * 演示 同步锁
 * @author zm
 * @date 2022/11/06
 */
public class SyncSample {
    static class Printer {
         public void print() {
            synchronized ("DADADADASDADAADADAD") {
                try {
                    Thread.sleep(500);
                    System.out.print("你");
                    Thread.sleep(500);
                    System.out.print("好");
                    Thread.sleep(500);
                    System.out.print("世");
                    Thread.sleep(500);
                    System.out.print("界");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        public  synchronized  void print1() {
                try {
                    Thread.sleep(500);
                    System.out.print("你");
                    Thread.sleep(500);
                    System.out.print("好");
                    Thread.sleep(500);
                    System.out.print("世");
                    Thread.sleep(500);
                    System.out.print("界");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        public  static synchronized  void print2() {
            try {
                Thread.sleep(500);
                System.out.print("你");
                Thread.sleep(500);
                System.out.print("好");
                Thread.sleep(500);
                System.out.print("世");
                Thread.sleep(500);
                System.out.print("界");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void start() {
        Printer printer = new Printer();
        for (int i = 0; i < 10; i++) {
            PrintTask printTask = new PrintTask();
            printTask.printer = printer;
            Thread thread = new Thread(printTask);
            thread.start();
        }

    }
    static class PrintTask implements Runnable {
        private  Printer printer;
        @Override
        public void run() {
                printer.print();
//                printer.print1();
//                Printer.print2();
        }
    }
    public static void main(String[] args) {
        new SyncSample().start();
    }
}

线程安全

  • 在 拥有 多条线程 并行执行的程序中,线程安全的代码 会通过同步机制保证各个线程可以正常 且正确的执行,不会出现数据污染的意外情况。

线程池

JUC 并发工具包 解决 同步 和 互斥问题
  • Runnable 新建 线程 , 性能差~~~
  • 线程 被频繁创建,相互竞争,严重时可能导致系统资源死机或者内存溢出
  • 线程池 ----- 线程复用
  • ThreadPool 线程池
    • 重用 存在的线程,减少线程对象的创建,消亡的开销
    • 线程总数可控,提高资源的利用率
    • 提供额外功能,定时执行,定期执行 和 监控。
  • 支持的线程池种类
    • 工具类 Executors(juc 包下) 创建线程池
    • FixedThreadPool - 定长线程池
    • CachedThreadPool - 可缓存的线程池
    • SingleThreadPool - 单线程池
    • ScheduledThreadPool - 调度线程池
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值