ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

多线程实现方式二

2026/8/13 14:17:20 拓冰建站 浏览量
多线程实现方式二

这里写目录标题

  • Runnable
    • Runable接口实现多线程
    • 使用Runnable接口实现多线程的好处
    • 线程同步 - 三个窗口买票
    • lock实现同步锁

Runnable

Runable接口实现多线程

  • 实现 Runnable 接口

    • 定义一个类 MyRunnable 实现 Runnable 接口

    • 在 MyRunnable 类中重写 run() 方法

    • 创建 Thread 类的对象,把 MyRunnable 对象作为构造方法的参数

    • 启动线程

demo:

定义一个类作为Runnable接口实现类

package com.itxs.demo05;/*** @Classname : MyRunnable* @Description : TODO* @Author : lin_refuel@qq.com*/
public class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 20; i++) {System.out.println(Thread.currentThread().getName() + " i = " + i);}}
}

测试类demo01

package com.itxs.demo05;/*** @Classname : demo01* @Description : TODO* @Author : lin_refuel@qq.com*/
public class demo01 {public static void main(String[] args) {MyRunnable mr = new MyRunnable();//创建线程Thread mt01 = new Thread(mr, "线程01");//Runnable接口实现类对象作为参数进行传递Thread mt02 = new Thread(mr, "线程02");Thread mt03 = new Thread(mr, "线程03");//匿名内部类方式实现new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 30; i++) {System.out.println(Thread.currentThread().getName()+" i = " + i);}}},"匿名线程").start();// 线程开启mt01.start();mt02.start();mt03.start();}
}

使用Runnable接口实现多线程的好处

  • 相比继承 Thread 类,实现 Runnable 接口的好处

    • 避免了 Java 单继承的局限性

    • 适合多个程序的代码同时处理一个资源的情况,把线程和程序的代码、数据有效的分离,较好的体现了面向对象程序设计的思想

线程同步 - 三个窗口买票

需求:德云社封箱演出共有 100 张门票,设置三个窗口买票,设计模拟买票的程序

思路:

  1. 定义一个 SellTickets 实现 Runnable 接口,里面定义一个成员:private int tickets = 100;

  2. 在 SellTickets 类中重写 run() 方法,实现买票

    1. 判断剩余票数是否大于 0,是就卖,并告知是哪个窗口卖出的

    2. 卖掉一张之后要对应减一

    3. 没有票了,也可能有人来买,用死循环让买票动作一直持续

  3. 顶一个测试类 SellTicketsTest,里面有 main() 方法

    1. 创建 SellTickets 类对象

    2. 创建三个 Thread 类的对象,把 SellTickets 对象作为构造方法的参数,并给出对应的窗口名称

    3. 启动线程

sycnchronized(任意对象){}:同步语句块,多个线程操作同一个资源时,当某个线程执行同步语句块里面的代码时,别的线程是无法执行的,只有当执行同步语句块线程执行完里面同步语句块的内容时,其他线程才能进行访问

  • 是否有多线程环境

  • 是否有共享数据

  • 是否有多条语句操作共享项数据

参考文章

demo:

卖票的动作,注意同步语句块的用法

package com.itxs.demo06;/*** @Classname : SellTickets* @Description : TODO* @Author : lin_refuel@qq.com*/
public class SellTickets implements Runnable {private int tickets = 100;// 门票数量为100@Overridepublic void run() {// 定义死循环,一直进行买票while (true){// 同步语句块,一个窗口抢到卖票权,其他窗口无法卖出同一个票synchronized (this){// 判断门票数是否大于0满足条件进行卖票if(tickets > 0){//打印出票System.out.println(Thread.currentThread().getName() +"正在买第 - "+this.tickets+"张门票");// 每次打印出票后,票数减去1this.tickets --;}}// 每个窗口卖出票后,等待出票try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

test测试类

package com.itxs.demo06;/*** @Classname : test* @Description : TODO 测试类* @Author : lin_refuel@qq.com*/
public class test {public static void main(String[] args) {//创建卖票动作的线程SellTickets st = new SellTickets();// 创建三个窗口进行买票Thread windows01 = new Thread(st, "窗口1");Thread windows02 = new Thread(st, "窗口2");Thread windows03 = new Thread(st, "窗口3");// 开始买票windows01.start();windows02.start();windows03.start();}
}

lock实现同步锁

还是上面的案例,通过lock方式实现线程同步

买票的类

package com.itxs.demo06;import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** @Classname : SellTickets* @Description : TODO* @Author : lin_refuel@qq.com*/
public class SellTickets implements Runnable {private int tickets = 100;// 门票数量为100private  Lock lock = new ReentrantLock();@Overridepublic void run() {// 定义死循环,一直进行买票while (true){// 同步语句块,一个窗口抢到卖票权,其他窗口无法卖出同一个票ticket();// 每个窗口卖出票后,等待出票try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}// 同步方法private /*synchronized*/ void ticket() {//synchronized (this){lock.lock();//上锁// 判断门票数是否大于0满足条件进行卖票if(this.tickets > 0){//打印出票System.out.println(Thread.currentThread().getName() +"正在买第 - "+this.tickets+"张门票");// 每次打印出票后,票数减去1this.tickets --;}//}lock.unlock();//开锁,!!!注意不要忘记开锁}
}

test测试类

package com.itxs.demo06;/*** @Classname : test* @Description : TODO 测试类* @Author : lin_refuel@qq.com*/
public class test {public static void main(String[] args) {//创建卖票动作的线程SellTickets st = new SellTickets();// 创建三个窗口进行买票Thread windows01 = new Thread(st, "窗口1");Thread windows02 = new Thread(st, "窗口2");Thread windows03 = new Thread(st, "窗口3");// 开始买票windows01.start();windows02.start();windows03.start();}
}