找回密码
 立即注册
首页 业界区 安全 第14章 多线程基础

第14章 多线程基础

卜笑 5 天前
第14章 多线程基础

14.1 线程相关概念

14.1.1 程序(program)

是为完成特定任务,用某种语言编写的一组指令的集合,即编写的代码。
示例代码(以Java为例):
  1. public class BallMove extends JFrame {
  2.     MyPanel mp = null;
  3.     public static void main(String[] args) {
  4.         BallMove ballMove = new BallMove();
  5.     }
  6.     public BallMove() {
  7.         mp = new MyPanel();
  8.         this.add(mp);
  9.         this.setSize(400, 300);
  10.         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  11.         this.setVisible(true);
  12.     }
  13. }
复制代码
14.1.2 进程


  • 运行中的程序,如启动QQ、迅雷,操作系统会为其分配内存空间。
  • 是程序的一次执行过程,有产生、存在和消亡的动态过程 。
14.1.3 线程


  • 由进程创建,是进程的实体,一个进程可拥有多个线程 。
  • 举例:后续会将多线程加入“坦克大战”游戏实践。
14.1.4 其他相关概念


  • 单线程:同一时刻仅允许执行一个线程。
  • 多线程:同一时刻可执行多个线程,如QQ同时开多个聊天窗口、迅雷同时下载多个文件 。
  • 并发:同一时刻多个任务交替执行,单CPU实现“貌似同时” 。
  • 并行:同一时刻多个任务真正同时执行,多核CPU可实现,Java支持。
14.2 线程基本使用

14.2.1 创建线程的两种方式(Java)


  • 继承Thread类:重写run方法,定义线程执行逻辑。
  • 实现Runnable接口:重写run方法,解决Java单继承局限,更灵活。
1.png

14.2.2 应用案例1 - 继承Thread类
  1. package com.ming.threaduse;
  2. /**
  3. * @author 明
  4. * @version 1.0
  5. * 演示通过继承Thread 类创建线程
  6. */
  7. public class Thread01 {
  8.     public static void main(String[] args) throws InterruptedException {
  9.         //创建Cat对象,可以当做线程使用
  10.         Cat cat = new Cat();
  11.         //读源码
  12.         /*
  13.             (1)
  14.             public synchronized void start() {
  15.                 start0();
  16.             }
  17.             (2)
  18.             //start0() 是本地方法,是JVM调用, 底层是c/c++实现
  19.             //真正实现多线程的效果, 是start0(), 而不是 run
  20.             private native void start0();
  21.          */
  22.         //cat.run();//run方法就是一个普通的方法, 没有真正的启动一个线程,就会把run方法执行完毕,才向下执行
  23.         //说明: 当main线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行
  24.         //这时 主线程和子线程是交替执行..
  25.         cat.start();//启动线程-> 最终会执行cat的run方法
  26.         System.out.println("主线程继续执行" +  Thread.currentThread().getName());
  27.         for (int i = 0; i < 10; i++) {
  28.             System.out.println("主线程 i= " + i);
  29.             //让主线程休眠
  30.             Thread.sleep(1000);
  31.         }
  32.     }
  33. }
  34. //说明
  35. //1.当一个类继承了Thread类,该类就可以当作线程使用
  36. //2. 我们会重写 run方法,写上自己的业务代码
  37. //3. run Thread 类 实现了 Runnable 接口的run方法
  38. /*
  39.     @Override
  40.     public void run() {
  41.         if (target != null) {
  42.             target.run();
  43.         }
  44.     }
  45. */
  46. class Cat extends Thread{
  47.     int times = 0;
  48.     @Override
  49.     public void run() {//重写run方法,写上自己的业务逻辑
  50.         while (true) {
  51.             System.out.println("喵喵,我是小猫咪"+times++ + Thread.currentThread().getName());
  52.             try {
  53.                 Thread.sleep(1000);
  54.             } catch (InterruptedException e) {
  55.                e.printStackTrace();
  56.             }
  57.             if(times==8){
  58.                 break;
  59.             }
  60.         }
  61.     }
  62. }
复制代码
2.png

14.2.3 应用案例2 - 实现Runnable接口

需求:每隔1秒在控制台输出“hi!”,输出10次后退出。
实现
  1. package com.ming.threaduse;
  2. import java.util.concurrent.Callable;
  3. import java.util.concurrent.FutureTask;
  4. /**
  5. * @author 明
  6. * @version 1.0
  7. * 通过实现接口Runnable 来开发线程
  8. */
  9. public class Thread02 {
  10.     public static void main(String[] args) throws InterruptedException {
  11. //        Dog dog = new Dog();
  12. //        //dog.start(); 这里不能调用start
  13. //        //创建了Thread对象,把 dog对象(实现Runnable),放入Thread
  14. //        Thread thread = new Thread(dog);
  15. //        thread.start();
  16.         Tiger tiger = new Tiger();
  17.         ThreadProxy threadProxy = new ThreadProxy(tiger);
  18.         threadProxy.start();
  19.     }
  20. }
  21. class Animal {
  22. }
  23. class Tiger extends Animal implements Runnable {
  24.     @Override
  25.     public void run() {
  26.         System.out.println("老虎嗷嗷叫....");
  27.     }
  28. }
  29. //线程代理类 , 模拟了一个极简的Thread类
  30. class ThreadProxy implements Runnable {//你可以把Proxy类当做 ThreadProxy
  31.    private Runnable target = null;//属性,类型是 Runnable
  32.     @Override
  33.     public void run() {
  34.         if (target != null) {
  35.             target.run();//动态绑定(运行类型Tiger)
  36.         }
  37.     }
  38.     public ThreadProxy(Runnable target) {
  39.         this.target = target;
  40.     }
  41.     public void start() {
  42.         start0();//这个方法时真正实现多线程方法
  43.     }
  44.     public void start0() {
  45.         run();
  46.     }
  47. }
  48. class Dog implements Runnable {
  49.     int count = 0;
  50.     @Override
  51.     public void run() {
  52.         while (true) {
  53.             System.out.println("小狗汪汪叫..hi" + (++count) + Thread.currentThread().getName());
  54.             //休眠1秒
  55.             try {
  56.                 Thread.sleep(1000);
  57.             }catch (Exception e){
  58.                 e.printStackTrace();
  59.             }
  60.             if(count == 10){
  61.                 break;
  62.             }
  63.         }
  64.     }
  65. }
复制代码
14..2.4线程使用应用案例-多线程执行
  1. package com.ming.threaduse;
  2. /**
  3. * @author 明
  4. * @version 1.0
  5. * main线程启动两个子线程
  6. */
  7. public class Thread03 {
  8.     public static void main(String[] args) {
  9.         T1 t1 = new T1();
  10.         T2 t2 = new T2();
  11.         Thread thread1 = new Thread(t1);
  12.         Thread thread2 = new Thread(t2);
  13.         thread1.start();
  14.         thread2.start();
  15.     }
  16. }
  17. class T1 implements Runnable{
  18.     int count = 0;
  19.     @Override
  20.     public void run() {
  21.         while (true) {
  22.             System.out.println("hello,world  " + (++count));
  23.             try {
  24.                 Thread.sleep(1000);
  25.             } catch (InterruptedException e) {
  26.                 e.printStackTrace();
  27.             }
  28.             if (count == 10){
  29.                 break;
  30.             }
  31.         }
  32.     }
  33. }
  34. class T2 implements Runnable{
  35.     int count = 0;
  36.     @Override
  37.     public void run() {
  38.         while (true) {
  39.             System.out.println("hi  " + (++count));
  40.             try {
  41.                 Thread.sleep(1000);
  42.             } catch (InterruptedException e) {
  43.                 e.printStackTrace();
  44.             }
  45.             if (count == 5){
  46.                 break;
  47.             }
  48.         }
  49.     }
  50. }
复制代码
3.png

4.png

14.3 继承Thread vs 实现Runnable的区别


  • 设计角度:Thread类本身实现Runnable接口,本质无区别,但实现接口更灵活。
  • 适用场景:实现Runnable适合多线程共享资源,且避免单继承限制,推荐优先使用。
  • 案例:售票系统
    模拟三个售票窗口售100张票,对比两种方式,分析线程安全等问题(如资源竞争导致超卖,后续需同步机制解决 )。
[code]package com.ming.ticket;import com.hspedu.ticket.SellTicket;/** * @author 明 * @version 1.0 * 使用多线程,模拟三个窗口同时售票100张 */public class SellTIcket {    public static void main(String[] args) {        //测试//        SellTicket01 sellTicket01 = new SellTicket01();//        SellTicket01 sellTicket02 = new SellTicket01();//        SellTicket01 sellTicket03 = new SellTicket01();////        //这里我们会出现超卖..//        sellTicket01.start();//启动售票线程//        sellTicket02.start();//启动售票线程//        sellTicket03.start();//启动售票线程        System.out.println("===使用实现接口方式来售票=====");        SellTicket02 sellTicket02 = new SellTicket02();        new Thread(sellTicket02).start();        new Thread(sellTicket02).start();        new Thread(sellTicket02).start();    }}//使用Thread方式class SellTicket01 extends Thread {    private static int ticketNum = 100;//让多个线程共享ticketNum    @Override    public void run() {        while (true){            if (ticketNum

相关推荐

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