卜笑 发表于 2025-8-27 15:56:50

第14章 多线程基础

第14章 多线程基础

14.1 线程相关概念

14.1.1 程序(program)

是为完成特定任务,用某种语言编写的一组指令的集合,即编写的代码。
示例代码(以Java为例):
public class BallMove extends JFrame {
    MyPanel mp = null;
    public static void main(String[] args) {
      BallMove ballMove = new BallMove();
    }
    public BallMove() {
      mp = new MyPanel();
      this.add(mp);
      this.setSize(400, 300);
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.setVisible(true);
    }
}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单继承局限,更灵活。

14.2.2 应用案例1 - 继承Thread类

package com.ming.threaduse;

/**
* @author 明
* @version 1.0
* 演示通过继承Thread 类创建线程
*/
public class Thread01 {
    public static void main(String[] args) throws InterruptedException {
      //创建Cat对象,可以当做线程使用
      Cat cat = new Cat();

      //读源码
      /*
            (1)
            public synchronized void start() {
                start0();
            }
            (2)
            //start0() 是本地方法,是JVM调用, 底层是c/c++实现
            //真正实现多线程的效果, 是start0(), 而不是 run
            private native void start0();

         */


      //cat.run();//run方法就是一个普通的方法, 没有真正的启动一个线程,就会把run方法执行完毕,才向下执行
      //说明: 当main线程启动一个子线程 Thread-0, 主线程不会阻塞, 会继续执行
      //这时 主线程和子线程是交替执行..
      cat.start();//启动线程-> 最终会执行cat的run方法

      System.out.println("主线程继续执行" +Thread.currentThread().getName());
      for (int i = 0; i < 10; i++) {
            System.out.println("主线程 i= " + i);
            //让主线程休眠
            Thread.sleep(1000);
      }
    }
}
//说明
//1.当一个类继承了Thread类,该类就可以当作线程使用
//2. 我们会重写 run方法,写上自己的业务代码
//3. run Thread 类 实现了 Runnable 接口的run方法
/*
    @Override
    public void run() {
      if (target != null) {
            target.run();
      }
    }
*/
class Cat extends Thread{

    int times = 0;
    @Override
    public void run() {//重写run方法,写上自己的业务逻辑


      while (true) {
            System.out.println("喵喵,我是小猫咪"+times++ + Thread.currentThread().getName());

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
               e.printStackTrace();
            }
            if(times==8){
                break;
            }
      }
    }
}
14.2.3 应用案例2 - 实现Runnable接口

需求:每隔1秒在控制台输出“hi!”,输出10次后退出。
实现:
package com.ming.threaduse;

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

/**
* @author 明
* @version 1.0
* 通过实现接口Runnable 来开发线程
*/
public class Thread02 {
    public static void main(String[] args) throws InterruptedException {
//      Dog dog = new Dog();
//      //dog.start(); 这里不能调用start
//      //创建了Thread对象,把 dog对象(实现Runnable),放入Thread
//      Thread thread = new Thread(dog);
//      thread.start();
      Tiger tiger = new Tiger();
      ThreadProxy threadProxy = new ThreadProxy(tiger);
      threadProxy.start();
    }
}

class Animal {
}

class Tiger extends Animal implements Runnable {

    @Override
    public void run() {
      System.out.println("老虎嗷嗷叫....");
    }
}

//线程代理类 , 模拟了一个极简的Thread类
class ThreadProxy implements Runnable {//你可以把Proxy类当做 ThreadProxy

   private Runnable target = null;//属性,类型是 Runnable

    @Override
    public void run() {
      if (target != null) {
            target.run();//动态绑定(运行类型Tiger)
      }
    }

    public ThreadProxy(Runnable target) {
      this.target = target;
    }

    public void start() {
      start0();//这个方法时真正实现多线程方法
    }

    public void start0() {
      run();
    }
}

class Dog implements Runnable {
    int count = 0;
    @Override
    public void run() {
      while (true) {
            System.out.println("小狗汪汪叫..hi" + (++count) + Thread.currentThread().getName());

            //休眠1秒
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
            if(count == 10){
                break;
            }
      }
    }
}14..2.4线程使用应用案例-多线程执行

package com.ming.threaduse;

/**
* @author 明
* @version 1.0
* main线程启动两个子线程
*/
public class Thread03 {
    public static void main(String[] args) {
      T1 t1 = new T1();
      T2 t2 = new T2();
      Thread thread1 = new Thread(t1);
      Thread thread2 = new Thread(t2);
      thread1.start();
      thread2.start();
    }
}
class T1 implements Runnable{
    int count = 0;
    @Override
    public void run() {
      while (true) {
            System.out.println("hello,world" + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 10){
                break;
            }
      }
    }
}

class T2 implements Runnable{
    int count = 0;
    @Override
    public void run() {
      while (true) {
            System.out.println("hi" + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 5){
                break;
            }
      }
    }
}

14.3 继承Thread vs 实现Runnable的区别


[*]设计角度:Thread类本身实现Runnable接口,本质无区别,但实现接口更灵活。
[*]适用场景:实现Runnable适合多线程共享资源,且避免单继承限制,推荐优先使用。
[*]案例:售票系统
模拟三个售票窗口售100张票,对比两种方式,分析线程安全等问题(如资源竞争导致超卖,后续需同步机制解决 )。
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
页: [1]
查看完整版本: 第14章 多线程基础