线程java代码实例[7个例子]

本文详细介绍了Java线程的创建和应用,包括通过继承Thread类和实现Runnable接口两种方式创建线程,线程参数传递,线程共享资源,以及多个线程同步的例子。例如,模拟3个站台售票、线程间同步控制取款和龟兔赛跑等,深入理解Java线程的关键概念和实践技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

例子部分参考验证:
https://blog.csdn.net/qq_34996727/article/details/80416277?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-3.channel_param

1 实现线程执行单元
把标题从 1 创建线程 更新为 1 实现线程执行单元的方式。
java中只有Thread代表线程。Runnable只是将业务相关的代码抽象为一个接口。这涉及到一种设计模式:策略模式。
因此创建线程new线程的方式只有一种。
实现线程执行单元线程体的方式有两种。

例1.继承Thread类方式
代码:

package com.whl.thread;

/**
 * 注:
 * java.lang包中放着java最核心最基础的类、接口:Object、System、Thread、Runnable
 * Thread.currentThread()获取当前cpu执行线程
 */
public class TestThread {
    public static void main(String[] args) {
        /**
         * step 3:在方法中新建一个刚才写的类
         */
        MyThread myThread = new MyThread();// 线程处于新建状态
        myThread.start();// 就绪状态
        for(int i = 0;i < 10;i++) {
            System.out.println("hello "+Thread.currentThread().getName());
        }
    }
}

/**
 * step 1:写一个类继承java.lang.Thread
 */
class MyThread extends Thread {
    /**
     * step 2:复写java.lang.Thread中的run()方法
     */
    @Override
    public void run() {// 运行
        // TODO 你的线程代码
        for(int i = 0;i < 10;i++) {
            System.out.println("hello "+Thread.currentThread().getName());
        }
    }
}

运行结果:
在这里插入图片描述
例2.实现Runnable接口方式
代码

package com.whl.thread;

public class TestThread2 {
    public static void main(String[] args) {
        /**
         * step 3:创建实现类
         */
        MyRunnable myRunnable = new MyRunnable();
        /**
         * step 4:创建Thread,传入实现类
         */
        Thread thread = new Thread(myRunnable);
        /**
         * step 5:调用start()方法
         */
        thread.start();
        for(int i = 0;i < 10;i++) {
            System.out.println("hello "+Thread.currentThread().getName());
        }
    }
}

/**
 * step 1:写一个Runnable接口的实现类
 */
class MyRunnable implements Runnable {
    /**
     * step 2:实现Runnable接口run()
     */
    @Override
    public void run() {
        for(int i = 0;i < 10;i++) {
            System.out.println("hello "+Thread.currentThread().getName());
        }
    }
}

运行结果
在这里插入图片描述
2 线程参数传递
例3.在实现类或继承类中写局部变量,通过有参构造、setget方式获取参数。
代码

package com.whl.thread;

public class TestThread3 {
    public static void main(String[] args) {
        /**
         * step 3:创建线程,创建实现类中传递实参
         */
        Thread t1 = new Thread(new MyRunnable2(23));
        t1.start();
        int i = 6;
        while(i-- > 0){
            System.out.println(Thread.currentThread().getName());
        }
    }
}
class MyRunnable2 implements Runnable {
    /**
     * step 1:在实现类中定义局部变量
     */
    private int age;

    /**
     * step 2:定义有参构造方法
     * @param age
     */
    public MyRunnable2(int age) {
        this.age = age;
    }
    @Override
    public void run() {
        int i = 6;
        while(i-- > 0){
            /**
             * step 4:使用参数
             */
            System.out.println(Thread.currentThread().getName() + " 我的年龄是->" + age);
        }
    }
}

运行结果
在这里插入图片描述
使用实现Runnable接口方式更好,原因:
java是单继承多实现;共享资源;数据和程序独立;
例4.两个线程共享资源实现代码:

package com.whl.thread;

public class TestThread3 {
    public static void main(String[] args) {
        MyRunnable2 myRunnable2 = new MyRunnable2();
        myRunnable2.setAge(23);
        // 两个线程共享变量age
        Thread t1 = new Thread(myRunnable2);
        Thread t2 = new Thread(myRunnable2);
        t1.start();
        t2.start();
        int i = 10;
        while(i-- > 0) {
            System.out.println(Thread.currentThread().getName());
        }
    }
}
class MyRunnable2 implements Runnable {
    /**
     * step 1:在实现类中定义局部变量
     * 两个线程共享
     */
    private int age;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public void run() {
        int i = 10;
        while(i-- > 0){
            this.age++;
            System.out.println(Thread.currentThread().getName() + " 我的年龄是->" + age);
        }
    }
}

运行结果:
在这里插入图片描述
3 线程应用例子
例5. 3个站台同时出售火车票,火车票共有20张
代码实现:

package com.whl.example.station;

/**
 * 注明:
 * static: 在类中的类前加上static,直接通过类名.类名调用;
 *          在类中的方法前加上static,直接通过类名.方法名调用;
 *          在类中的变量前加上static,直接同多类名.变量名访问;
 * 静态变量生命周期是类的生命周期;
 *
 * step 1: 创建一个站台类继承java.lang.Thread
 */
public class Station extends Thread {
    /**
     * step 2: 创建有参构造方法,给线程名称赋值
     * @param name
     */
    public Station(String name) {
        super(name);
    }
    /**
     * step 3:创建静态变量,类的变量
     */
    static int tick = 20;
    /**
     * step 4: 创建静态钥匙,类的变量
     *
     * 关键思想:通过[静态,没有static关键字可正常运行]变量的占用判断是否对另一个静态变量操作
     */
     Object lock = "one";

    /**
     * step 5: 重写run()方法,实现买票操作
     */
    @Override
    public void run() {
        while(tick > 0) {
            /**
             * step 6: 每个线程使用同一静态变量,一个线程占用该静态变量时,其他线程不允许进入
             *          该线程出来这个代码块后,不使用该静态变量
             *
             * 关键思想:synchronized与静态变量lock配合,操作系统保证cpu只运行三个线程中唯一一个线程中此段代码,
             *           其他线程不能被执行。唯一一个线程的此段代码运行结束后,cpu可同步执行3个线程线程。
             */
            synchronized (lock) {
                if(tick > 0) {
                    System.out.println(getName()+"卖出了第"+tick+"张票");
                    tick--;
                }else {
                    System.out.println("票卖完了");
                }
            }
            try {
                sleep(500);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}


package com.whl.example.station;

public class Main {
    public static void main(String[] args) {
        /**
         * step 7: 创建继承类售票窗口
         *          3个窗口
         */
        Thread t1 = new Station("售票窗口1号");
        Thread t2 = new Station("售票窗口2号");
        Thread t3 = new Station("售票窗口3号");
        /**
         * step 8: 三个窗口都处于就绪状态
         */
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果:
在这里插入图片描述问题:同步关键字为什么不写在循环外?
同步关键字写在循环外面代码:

@Override
public void run() {
    synchronized (lock){while(tick > 0) {
        /**
         * step 6: 每个线程使用同一静态变量,一个线程占用该静态变量时,其他线程不允许进入
         *          该线程出来这个代码块后,不使用该静态变量
         *
         * 关键思想:synchronized与静态变量lock配合,操作系统保证cpu只运行三个线程中唯一一个线程中此段代码,
         *           其他线程不能被执行。唯一一个线程的此段代码运行结束后,cpu可同步执行3个线程线程。
         */

            if(tick > 0) {
                System.out.println(getName()+"卖出了第"+tick+"张票");
                tick--;
            }else {
                System.out.println("票卖完了");
            }

        try {
            sleep(500);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}}

运行结果:
在这里插入图片描述
结论:同步关键字修饰的代码块,被单独执行。
例6.两个人,一个人每次取钱100元,一个人每次取钱200元,账户里有1000元.
代码实现:

package com.whl.example.person;

import java.util.Objects;

/**
 * step 1:创建银行类
 */
public class Bank {
    /**
     * 创建一个账户,放1000元
     * [有没有 static 不影响结果]
     */
    double money = 1000;

    /**
     * 提供柜台取钱方法
     * @param money
     */
    private void counter(double money) {
        this.money -= money;
        System.out.println("柜台取钱"+money+"元,还剩"+this.money+"元!");
    }

    /**
     * 提供atm取钱方法
     * @param money
     */
    private void atm(double money) {
        this.money -= money;
        System.out.println("atm取钱"+money+"元,还剩"+this.money+"元!");
    }

    /**
     * 核心:只要有一个线程被cpu正在执行这个取钱方法,其他都不准执行。
     *
     * 提供取钱方法,设置每次取钱金额,取钱方式
     * @param money
     * @param mode
     * @throws Exception
     */
    public synchronized void outMoney(double money,String mode) throws Exception {
        if(money > this.money) {
            throw new Exception("取款金额"+money+",余额只剩"+this.money+",取款失败!");
        }
        if(Objects.equals(mode,"atm")) {
            atm(money);
        }else {
            counter(money);
        }
    }
}

package com.whl.example.person;

/**
 * step 2:创建一个人继承java.lang.Thread
 */
public class PersonA extends Thread {
    Bank bank;
    String mode;
    public PersonA(Bank bank,String mode) {
        this.bank = bank;
        this.mode = mode;
    }

    /**
     * 每次取钱100,柜台取钱
     */
    public void run(){
        while(bank.money >= 100) {
            try{
                bank.outMoney(100,mode);
            }catch (Exception e) {
                e.printStackTrace();
            }
            try{
                sleep(100);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

package com.whl.example.person;
/**
 * step 3:创建一个人继承java.lang.Thread
 */
public class PersonB extends Thread {
    /**
     * 创建账户
     */
    Bank bank;
    /**
     * 创建取钱方式
     */
    String mode;

    /**
     * 提供设置具体取钱方式及账户的方法
     * @param bank
     * @param mode
     */
    public PersonB(Bank bank,String mode) {
        this.bank = bank;
        this.mode = mode;
    }

    /**
     * 每次取钱200元,atm取钱
     */
    public void run(){
        while(bank.money >= 200) {
            try{
                bank.outMoney(200,mode);
            }catch (Exception e) {
                e.printStackTrace();
            }
            try{
                sleep(100);
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

package com.whl.example.person;

/**
 * step 4:创建一个入口类
 */
public class Main {
    public static void main(String[] args) {
        /**
         * 实例化一个银行账户
         */
        Bank bank = new Bank();
        /**
         * 实例化两个继承类,共享这个银行账户
         */
        PersonA personA = new PersonA(bank,"counter");
        PersonB personB = new PersonB(bank,"atm");
        /**
         * 线程处于就绪状态
         */
        personA.start();
        personB.start();
    }
}

运行结果:
在这里插入图片描述
例7.龟兔赛跑
总共200米
乌龟0.1秒跑2米,不休息
兔子0.1秒跑5米,每20米休息1秒
一个赢了,另一个停止跑
实现代码:

package com.whl.example.animal;

public abstract class Animal extends Thread {
    /**
     * 比赛长度
     */
    public int length = 200;

    /**
     * 抽象方法
     * 动物跑
     */
    public abstract void running();

    /**
     * 复写run()
     */
    public void run(){
        super.run();
        while (length > 0) {
            running();
        }
    }

    /**
     * 抽象类中声明一个接口
     */
    public static interface Calltoback {
        public void win();
    }
    /**
     * 创建接口对象
     */
    public Calltoback calltoback;
}

package com.whl.example.animal;

public class Rabbit extends Animal {
    public Rabbit() {
        setName("兔子");
    }

    @Override
    public void running() {
        int dis = 5;
        length -= dis;
        System.out.println("兔子跑了"+dis+"米,距离终点还有"+length+"米");
        if(length <= 0) {
            length = 0;
            System.out.println("兔子赢了!");
            // 给回调对象赋值,让乌龟不要跑了
            if(calltoback != null) {
                calltoback.win();
            }
        }
        try {
            if((2000 - length) % 20 == 0) {// 每20米休息一次
                sleep(1000);
            }else {
                sleep(100);// 每0.1秒跑5米
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

package com.whl.example.animal;

public class Tortoise extends Animal {
    public Tortoise() {
        setName("乌龟");
    }
    @Override
    public void running() {
        int dis = 2;
        length -= dis;
        System.out.println("乌龟跑了"+dis+"米,距离终点还有"+length+"米");
        if(length <= 0) {
            length = 0;
            System.out.println("乌龟赢了!");
            if(calltoback != null) {
                calltoback.win();
            }
        }
        try {
            sleep(100);// 跑2米停0.1秒 -> 每0.1秒跑2米
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

package com.whl.example.animal;

public class LetOneStop implements Animal.Calltoback {
    Animal animal;
    public LetOneStop(Animal animal) {
        this.animal = animal;
    }
    public void win(){
        // 线程停止
        animal.stop();
    }
}

package com.whl.example.animal;

public class Main {
    public static void main(String[] args) {
        // 乌龟
        Tortoise tortoise = new Tortoise();
        // 兔子
        Rabbit rabbit = new Rabbit();
        // 兔子赢了,将乌龟停止
        LetOneStop letOneStop1 = new LetOneStop(tortoise);
        rabbit.calltoback = letOneStop1;
        // 乌龟赢了,将兔子停止
        LetOneStop letOneStop2 = new LetOneStop(rabbit);
        tortoise.calltoback = letOneStop2;
        // 跑
        tortoise.start();
        rabbit.start();
    }
}

运行结果:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值